С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/39: Рейтинг темы: голосов - 39, средняя оценка - 5.00
4 / 4 / 0
Регистрация: 24.10.2010
Сообщений: 200
1

Виртуальный методы, абстрактный класс.

26.02.2012, 22:50. Показов 7728. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.
Теоретические вопросы.
Что такое виртуальный методы и что такое абстрактный класс.
Можете объяснить своими словами без ссылок на википедию.
Заранее спасибо.
0
IT_Exp
Эксперт
8794 / 1073 / 104
Регистрация: 17.06.2006
Сообщений: 12,602
Блог
26.02.2012, 22:50
Ответы с готовыми решениями:

Виртуальный абстрактный класс
Надеюсь мой вопрос будет не глупым. Есть класс исключений в пространстве имен std У него есть...

Абстрактный класс. Виртуальный метод, который возвращает T- тип
Привет! Допустим, есть абстрактный класс, и метод, который возвращает T-тип. class A {...

Абстрактный класс «Клиент банка», имеющий виртуальный метод для вывода данных о клиенте
Создать абстрактный класс «Клиент банка», имеющий поля ФИО и адрес, а также метод, для вывода...

Абстрактный класс, виртуальные методы
Учащийся: школьник, студент, аспирант. Каждый учащийся характеризуется: ФИО строки), дата рождения,...

16
117 / 74 / 6
Регистрация: 23.01.2012
Сообщений: 186
26.02.2012, 23:40 2
Если несколько упрощать:
Абстрактный класс - Класс который описывает только прототипы функций без их реализации(в терминологии С++ интерфейс) , соответственно раз нет реализации не одного метода(функции), то нельзя создать экземпляр этого класса. Используется для того что бы все наследники этого класса имели не взирая, что они делают, единый интерфейс(вызов методов).
Виртуальный метод (функция) - Это такая функция которая переписана для каждого наследника класса. И определения какую функцию вызывать, программа будет решать не в момент написания кода, а в момент его выполнения. Допустим у вас три класcа:
B - базовый
N1 - наследник от B
N2 - наследник от B или N1
во всех трех классах есть виртуальная функция "V" которая в разных классах выполняет различные действия.
И есть в программе функция "f" которая в качестве аргумента получает указатель на базовый класс и имеет следущею реализацию В->V();
Теперь в эту функцию, Вы можете передать в качестве аргумента, класс B или N1 или N2 и будет выполнена функции V именно того класса который Вы передали.
Ну если коротенько, то гдето так.
2
Эксперт С++
5057 / 3117 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
27.02.2012, 23:55 3
Цитата Сообщение от _engineer_ Посмотреть сообщение
Класс который описывает только прототипы функций без их реализации
Не обязательно. Чтобы быть абстрактным, класс должен содержать чистую виртуальную функцию. Из такого определения вытекает, что класс может содержать 100 обычных функцию с реализациями (даже не виртуальных) и одну чистую виртуальную, и тогда он будет абстрактным.

Цитата Сообщение от _engineer_ Посмотреть сообщение
(в терминологии С++ интерфейс)
В терминологии С++ как раз-таки нет понятия "интерфейсы". Так что это замена интерфейсам. С другой стороны, в таких языках, как Java и C# есть как интерфейсы, так и абстрактные классы.

Цитата Сообщение от _engineer_ Посмотреть сообщение
соответственно раз нет реализации не одного метода(функции), то нельзя создать экземпляр этого класса.
И снова - достаточно, чтобы не было реализации хотя бы одного метода (он должен быть объявлен как чисто виртуальный - virtual type method(parameters) = 0;), то нельзя создать объект такого класса, потому что он становится абстрактным. Независимо от реализаций и виртуальности остальных его методов.

Цитата Сообщение от _engineer_ Посмотреть сообщение
Это такая функция которая переписана для каждого наследника класса
Не обязательно. Класс-наследник может безболезненно использовать реализацию класса-родителя.
Виртуальный метод - это метод, конкретная реализация которого определяется во время исполнения программы на основании типа объекта, из которого был вызван метод.
1
44 / 44 / 17
Регистрация: 28.01.2012
Сообщений: 341
22.05.2013, 00:52 4
А у меня есть такой вопрос по абстрактным классам и виртуальным функциям.
Если в абстрактном классе, к примеру 2 виртуальные функции (не важно чисто виртуальные или нет), то в производном классе не могут же существовать другие методы, кроме этих 2-х переопределенных? Точнее они могут существовать, но если что-то типа такого
C++
1
2
BaseClass * pointer = new ChildClass();
pointer->SobstvenniyChaildMetodKotorogoNetVBase();
то компилятор ругается, что нету такой функции.
0
Эксперт С++
5057 / 3117 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
22.05.2013, 12:16 5
Цитата Сообщение от akk Посмотреть сообщение
то компилятор ругается, что нету такой функции.
Разумеется. Родитель ничего не знает о дополнениях, добавленных в наследнике, в том числе о новых методах. А раз этого не знает родитель, то этого не знает и компилятор, поэтому в случае попытки вызова метода, появившегося только в потомке, компилятор скажет, что такого метода в предке не существует. С тем же успехом можно попытаться вызвать через указатель на наследника метод, которого вообще нет ни в одном классе программы.
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
22.05.2013, 12:54 6
Цитата Сообщение от akk Посмотреть сообщение
то компилятор ругается, что нету такой функции.
Если нужно вызвать метод дочернего класса (которого не было в базовом), имея только указатель базового типа, то можно использовать приведение типа:
C++
1
2
BaseClass * pointer = new ChildClass();
dynamic_cast<ChildClass*>(pointer)->SobstvenniyChaildMetodKotorogoNetVBase();
По-хорошему, еще не помешает проверка после приведения.
1
Эксперт С++
5057 / 3117 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
22.05.2013, 13:17 7
Цитата Сообщение от Tulosba Посмотреть сообщение
то можно использовать приведение типа
Да, этот способ имеет место быть. Но зачастую его применение говорит об изначальной непродуманности самой архитектуры.

Цитата Сообщение от Tulosba Посмотреть сообщение
По-хорошему, еще не помешает проверка после приведения.
А вот это надо делать не "по-хорошему", а всегда.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
22.05.2013, 13:24 8
Цитата Сообщение от silent_1991 Посмотреть сообщение
А вот это надо делать не "по-хорошему", а всегда.
В данном случае из 2х строк даже не представляю, что должно произойти, чтобы pointer не привелся к типу ChildClass*, т.е. вернул nullptr.
0
Эксперт С++
5057 / 3117 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
22.05.2013, 13:28 9
Цитата Сообщение от Tulosba Посмотреть сообщение
В данном случае из 2х строк даже не представляю, что должно произойти, чтобы pointer не привелся к типу ChildClass*, т.е. вернул nullptr.
Если в данном случае используется такой подход, то проблема не в архитектуре, а в голове автора (к вам, разумеется, не относится, ибо это пример). Не могу представить себе ситуацию, когда на одной странице кода было бы видно создание объекта дочернего класса, присваивание его адреса ссылке/указателю на базовый класс, и приведение этой ссылки/указателя к ссылку/указателю на дочерний класс. Но, в любом случае, я бы всё равно сделал проверку. Код имеет свойство разрастаться, при этом и посредством вклинивания новых строк между существующими.
0
44 / 44 / 17
Регистрация: 28.01.2012
Сообщений: 341
22.05.2013, 19:34 10
А если делать проверку то у меня работает только так:
C++
1
2
3
4
if (pointer[i]=dynamic_cast<ClassChild*>(pointer[i]))
 {
dynamic_cast<ClassChild*>(goods[i])->GetMetodChild(); 
}
Всегда нужно получается приводит, т е перед каждым методом писать dynamic_cast<ClassChild*>(goods[i])->GetMetodChild(); то есть у меня почему-то в if не получается такое присваивания или так и должно быть.
0
Эксперт С++
5057 / 3117 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
22.05.2013, 19:38 11
akk, потому что pointer[i] имеет тип ClassBase *, к которому во время присваивания автоматически приводится указатель, полученный после dynamic_cast. Делать надо так:
C++
1
2
3
ClassChild *cc_ptr = dynamic_cast<ClassChild *>(pointer[i]);
if (cc_ptr)
    cc_ptr->GetMethodChild();
Добавлено через 1 минуту
А вообще, какое отношение проверяемый pointer[i] имеет к goods[i], из которого вызывается метод? Если вызываете из goods[i], то и проверять надо именно его.
1
44 / 44 / 17
Регистрация: 28.01.2012
Сообщений: 341
22.05.2013, 19:40 12
silent_1991, т е надо использовать другой временный указатель подкласса, и под ним выполнять методы? Но так данные не потеряются?
0
Эксперт С++
5057 / 3117 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
22.05.2013, 19:40 13
akk, а куда они потеряются-то? Это же указатель, а не копия объекта.
0
44 / 44 / 17
Регистрация: 28.01.2012
Сообщений: 341
22.05.2013, 19:54 14
Цитата Сообщение от silent_1991 Посмотреть сообщение
Это же указатель, а не копия объекта.
Ну так если память выделяется динамически, а потом происходит приведения к другому типу, и заполняется методами подкласса?

Добавлено через 9 минут
И если к примеру имеется еще один указатель базового класса, то можно сделать просто так или тоже надо приводить.

C++
1
2
3
4
5
6
7
8
9
10
Base * pointer1, * pointer2;
pointer1 = new ChildClass();
ChildClass * ptr = dynamic_cast<ChildClass *>(pointer1);
if(ptr)
    //заполняем данными класс
 
pointer2=pointer1;
ChildClass * p = dynamic_cast<ChildClass *>(pointer2);
if(p)
//просматриваем к примеру введенные данные
т е безбоязненно такое присваивание будет pointer2=pointer1 ?
0
Эксперт С++
5057 / 3117 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
22.05.2013, 20:10 15
akk, вам бы подучить основы, а потом уже приступать к полиморфизму. Никакая память никакими методами не заполняется. Вы полагаете, что каждый объект хранить все методы своего класса? Это неверно. Методы в программе располагаются в единственном экземпляре. Полиморфизм работает благодаря тому, что каждый объект хранит ссылку на таблицу виртуальных методов своего класса. Т.е. в vtable объекта типа ChildClass есть указатели на все виртуальные методы ChildClass, в том числе на те, которых нет в BaseClass. Но если адрес этого объекта присвоен указателю на BaseClass, компилятор просто не знает, что по этому указателю на самом деле лежит объект типа ClassChild с расширенной по отношению к BaseClass таблицей виртуальных методов. Приведение вниз посредством dynamic_cast заставляет компилятор понять, что на самом деле используется vtable класса ChildClass, и позволить нам вызвать методы, добавленные в этом классе.

Код вашего примера не понял, как и вопроса касательно него. В данном случае pointer1 и pointer2 в конечном счёте будут указывать на один и тот же объект типа ChildClass. Если хотите вызывать методы, добавленные в ChildClass, как через pointer1, так и через pointer2 - надо делать приведение вниз.

Добавлено через 6 минут
Цитата Сообщение от silent_1991 Посмотреть сообщение
Приведение вниз посредством dynamic_cast заставляет компилятор понять, что на самом деле используется vtable класса ChildClass, и позволить нам вызвать методы, добавленные в этом классе.
Вернее сказать даже не так. dynamic_cast играет роль только во время выполнения. Компилятору наплевать на vtable, ему важно, чтобы тип указателя, через который вызывается метод, содержал этот вызываемый метод.
1
44 / 44 / 17
Регистрация: 28.01.2012
Сообщений: 341
22.05.2013, 20:14 16
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Base * pointer1, * pointer2;
pointer1 = new ChildClass();
ChildClass * ptr = dynamic_cast<ChildClass *>(pointer1);
if(ptr)
    ptr->GetMetod();
//... 
pointer2=pointer1;
pointer1=NULL;
//...
ptr = dynamic_cast<ChildClass *>(pointer2);
if(ptr)
    ptr->GetMetod(); //тоже самое что и выше
//...
delete pointer2;
Так можно делать?
0
Эксперт С++
5057 / 3117 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
22.05.2013, 20:16 17
Цитата Сообщение от akk Посмотреть сообщение
Так можно делать?
За исключением того, что в строках 3 и 10 нужно использовать разные имена, да, не вижу препятствий сделать так (как не вижу и того, что вас смущает в этом коде).
1
22.05.2013, 20:16
BasicMan
Эксперт
19315 / 2622 / 84
Регистрация: 17.02.2009
Сообщений: 10,364
Блог
22.05.2013, 20:16
Помогаю со студенческими работами здесь

Объясните как объявить абстрактный класс, и при этом не тащить виртуальные методы в производные классы
Суть вопроса - есть у меня класс, который я решаю сделать абстрактным. Как я понимаю что бы сделать...

абстрактный класс как реализовать данные, над которыми методы выполняют какие-либо действия
Абстрактный класс как реализовать данные, над которыми методы выполняют какие-либо действия...

Опишите абстрактный базовый класс "строка",реализующий методы ввода-вывода строки
Кто поможет,тому магарыч. Опишите абстрактный базовый класс &quot;строка&quot;,реализующий методы...

Класс: Разработать абстрактный класс класс Point для задания координаты...
Всем привет, помогите пожалуйста решить задачу, я уже всю голову сломал, не знаю как решить... ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Блоги программистов
Как использовать GraphQL в C# с HotChocolate
Programming 05.01.2025
GraphQL — это современный подход к разработке API, который позволяет клиентам запрашивать только те данные, которые им необходимы. Это делает взаимодействие с API более гибким и эффективным по. . .
Модель полного двоичного суматора с помощью логических операций (python)
AlexSky-coder 04.01.2025
def binSum(x:list, y:list): s=^y] p=x and y for i in range(1,len(x)): s. append((x^y)^p) p=(x and y)or(p and (x or y)) return s x=list() y=list()
Это мы не проходили, это нам не задавали...(шес­­­­­­­­­­­­­­­ти­б­и­т­н­ы­й асихронный счётчик с управляющим сигналом заде
Hrethgir 04.01.2025
Асинхронный счётчик на сумматорах (шестиразрядный по числу диодов на плате, но наверное разрядов будет больше - восемь или шестнадцать, а диоды на старшие), так как триггеры прошли тестирование и. . .
Руководство по созданию бота для Телеграм на Python
IT_Exp 04.01.2025
Боты для Телеграм представляют собой автоматизированные программы, которые выполняют различные задачи, взаимодействуя с пользователями через интерфейс мессенджера. В данной статье мы рассмотрим,. . .
Применение компонентов PrimeVue в Vue.js 3 на TypeScript
BasicMan 04.01.2025
Введение в PrimeVue и настройка окружения PrimeVue представляет собой мощную библиотеку компонентов пользовательского интерфейса для Vue. js 3, которая предоставляет разработчикам богатый набор. . .
Как стать Senior developer
cpp_developer 04.01.2025
В современной индустрии разработки программного обеспечения позиция Senior Developer представляет собой не просто следующую ступень карьерной лестницы, а качественно новый уровень профессионального. . .
Что известно о дате выхода Windows 12 и чего от нее ждать
IT_Exp 04.01.2025
В мире технологий постоянно происходят изменения, и операционные системы не являются исключением. Windows 11, выпущенная в октябре 2021 года, принесла множество инноваций и улучшений, но. . .
Что новенького в .NET Core 9
Programming 04.01.2025
Обзор ключевых изменений в . NET Core 9 Платформа . NET Core продолжает активно развиваться, и версия 9 представляет собой значительный шаг вперед в эволюции этой технологии. Новый релиз. . .
Инструкция по установке python3.13.1 в Debian 12
AlexSky-coder 03.01.2025
sudo apt update sudo apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget. . .
Затестил триггеры. архив проекта прилагаю с GOA файлами в настройках архиватора проектов.
Hrethgir 03.01.2025
В этот раз нет закольцованности, потому что от неё только глюки, как я понял, логика не вырезанная. Триггеры очень быстрые если верить измерениям с помощью анализатора от Gowin. Есть ещё регистры,. . .
Python в помощь DevOps
IT_Exp 03.01.2025
Причины использования Python в работе DevOps Python стал неотъемлемой частью мира DevOps, и это не случайно. Этот язык программирования обладает множеством преимуществ, которые делают его. . .
Angular vs React vs Vue.js
BasicMan 03.01.2025
О, друзья-разработчики и просто любопытные читатели! Сегодня мы отправимся в увлекательное путешествие по миру фронтенд-разработки, и первой остановкой станет Angular – этакий строгий немецкий. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru