Как работает полиморфизм при работе с массивами дочерних объектов?
Мне нужно, чтобы объекты класов child и child2 , к примеру находились в одном массиве. Если я создам массив элементов base , я смогу обращаться к ним через интерфейс? Или обязательно создавать массив объектов interface ? Т. е. если я укажу тип данных base для массива, компилятор все равно выделит память под полный тип данных объекта включая interface ? Или нет?
Отслеживать
задан 24 фев 2018 в 15:53
107 1 1 серебряный знак 8 8 бронзовых знаков
Массив может содержать только элементы одного типа, поэтому объекты класов child и child2 не могут находиться в одном массиве.
24 фев 2018 в 15:57
Насколько мне известно в массиве элементов базового класса могут храниться объекты дочерних классов, полиморфизм как-ни-как))
24 фев 2018 в 16:05
Полиморфизм тут не при чем, и в массиве элементов базового класса объекты других типов храниться не могут.
24 фев 2018 в 16:06
Оно компилируется, но в массиве будут только объекты базового типа. А компилируется оно потому, что вы забыли запретить конструкторы и операторы копирования / перемещения. base obj; child cobj; obj = cobj; у вас тоже будет компилироваться, но в переменной obj по-прежнему будет объект типа base . Инициализация и присвоение не могут изменить тип объекта. А код можно добавить отредактировав вопрос.
24 фев 2018 в 16:29
Нет, это потому что массив является гомогенным контейнером, то есть по определению содержит только элементы одного типа. Аналогичный гетерогенный контейнер — это кортеж. При этом у обоих тип всех элементов зафиксирован во время компиляции.
24 фев 2018 в 16:41
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Если вы создадите массив объектов base , то, как вы понимаете, каждому объекту будет выделена память только под base , и вы получите при присваивании срезку.
Используйте массив указателей на base — и все получится 🙂
Еще — непонятно, зачем вы делаете child производным и от base , и от interface , при том, что interface является производным от base . Не то чтобы это было запрещено. но это очень специфичное решение, которое вряд ли вам необходимо, скорее, вы немного недоразобрались в вопросе.
Да, и override пишется с другой стороны объявления 🙂
Как создать массив полиморфных объектов c
Доброго времени суток, уважаемые коллеги !
Есть контейнер полиморфных типов — допустим это vector vec;
В нём хранятся объекты типов ItemA, ItemB, ItemC и т.д.
Задача состоит в получении из этого контейнера второго элемента типа ItemB. Или же списка всех элементов типа ItemB.
Для общего случая — это n-ный элемент типа T.
Пока набросал вот такое:
class Item < public: Item(string text) < _text = text; >virtual void f() <> string text() const < return _text; > private: string _text; >; class ItemA : public Item < public: ItemA(string text) : Item(text) <> >; class ItemB : public Item < public: ItemB(string text) : Item(text) <> >; template class ItemType> ItemType* get(vector vec, int index) < int count = 0; for(size_t i = 0; i < vec.size(); ++i) < ItemType* item = dynamic_cast(vec[i]); if(item) < if(index == count) < return item; > count++; > > return 0; > int main(int argc, char* argv[]) < vectorvec; vec.push_back(new ItemA("itemA")); vec.push_back(new ItemB("itemB1")); vec.push_back(new ItemB("itemB2")); ItemB* itemB = get(vec, 0); if(itemB) < cout text() return 0; >
Может есть более толковые решения ?
Re: полиморфный массив объектов — найти n-ный элемент типа T
| От: | ilnar |
| Дата: | 18.11.08 15:27 |
| Оценка: |
Здравствуйте, chipmunk, Вы писали:
C>Может есть более толковые решения ?
например, не смешивать
Re: полиморфный массив объектов — найти n-ный элемент типа T
| От: | игппук |
| Дата: | 18.11.08 16:54 |
| Оценка: |
имхо, нормальное решение. только я бы класс Item расширил та
class Item < template class ItemType> virtual bool IsType(ItemType& _item) = 0; >
и внутри метода IsType проводил бы всю необходимую работу по получении типа объекта.
проклятый антисутенерский закон
Re[2]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Bell | |
| Дата: | 19.11.08 02:38 | |
| Оценка: | 6 (1) | |
Здравствуйте, игппук, Вы писали:
И>имхо, нормальное решение. только я бы класс Item расширил та
И>
И>class Item И> < И>template class ItemType> И> virtual bool IsType(ItemType& _item) = 0; И>> И>
И>и внутри метода IsType проводил бы всю необходимую работу по получении типа объекта.
14.5.2/3
A member function template shall not be virtual.
Любите книгу — источник знаний (с) М.Горький
Re[3]: полиморфный массив объектов — найти n-ный элемент тип
| От: | alexeiz |
| Дата: | 19.11.08 05:21 |
| Оценка: |
Здравствуйте, Bell, Вы писали:
B>
B>14.5.2/3
B>A member function template shall not be virtual.
Евангелие от Бьярна.
Re[4]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Bell |
| Дата: | 19.11.08 05:28 |
| Оценка: |
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, Bell, Вы писали:
B>>
B>>14.5.2/3
B>>A member function template shall not be virtual.
A>Евангелие от Бьярна.
Нет, в данном случае от ISO/IEC 14882
Любите книгу — источник знаний (с) М.Горький
Re: полиморфный массив объектов — найти n-ный элемент типа T
| От: | Кодт | |
| Дата: | 19.11.08 10:35 | |
| Оценка: | 4 (2) +1 | |
Здравствуйте, chipmunk, Вы писали:
C>Доброго времени суток, уважаемые коллеги !
C>Есть контейнер полиморфных типов — допустим это vector vec;
C>В нём хранятся объекты типов ItemA, ItemB, ItemC и т.д.
C>Задача состоит в получении из этого контейнера второго элемента типа ItemB. Или же списка всех элементов типа ItemB.
C>Для общего случая — это n-ный элемент типа T.
<>
C>Может есть более толковые решения ?
Толковые решения состоят в задействовании стандартных алгоритмов, добавляя необходимые точки кастомизации. В данном случае такая точка кастомизации — предикат проверки типа.
templateclass Base, class Derived> bool is_dynamic_type(Base* p) < return !p || dynamic_cast(p); > templateclass Base, class Derived> Derived* do_dynamic_cast(Base* p) < return dynamic_cast(p); > /////////////////////////// std::vector items; . std::vector::const_iterator first_b = std::find_if(items.begin(), items.end(), is_dynamic_type); std::vector itemsB; std::transform(items.begin(), items.end(), std::back_inserter(itemsB), do_dynamic_cast); // трансформируем. itemsB.erase(std::remove(itemsB.begin(), itemsB.end(), NULL), itemsB.end()); // . и удаляем неудачные результаты
Ну и тому подобное. Можно ещё припахать boost/iterator, boost/algo — там есть всякие удобные трансформаторы, чтобы, например, бегать только по удовлетворяющим условию элементам.
Перекуём баги на фичи!
Re: полиморфный массив объектов — найти n-ный элемент типа T
| От: | Аноним |
| Дата: | 20.11.08 10:04 |
| Оценка: |
Здравствуйте, chipmunk, Вы писали:
C>Доброго времени суток, уважаемые коллеги !
C>Есть контейнер полиморфных типов — допустим это vector vec;
C>В нём хранятся объекты типов ItemA, ItemB, ItemC и т.д.
варианты основанные на dynamic_cast работают только в случае двухуровневой иерархии, а в случае большего количества уровней дают замечательные артефакты т.к. объект низшего уровня может быть любым из объектов более высокого уровня. В общем случае можно сделать как-то так:
class Item < public: Item(const std::type_info& type) : _typename(type.name()) <>virtual const std::string& typename() < return _typename; >private: const std::string _typename; >; class ItemA : public Item < public: ItemA() : Item(typeid(ItemA)) <>// не уверен что тут можно использовать this. ItemA(const std::type_info& type) : Item(type) <> >; class ItemAA : public ItemA < public: ItemAA() : ItemA(typeid(ItemAA)) <>ItemAA(const std::type_info& type) : ItemA(type) <> >;
но лучше подумайте над дизайном и не скрещивайте ужа и ежа, желание получить производный тип из базового говорит о неправильном дизайне.
Re: полиморфный массив объектов — найти n-ный элемент типа T
| От: | IROV.. |
| Дата: | 21.11.08 10:02 |
| Оценка: |
Здравствуйте, chipmunk, Вы писали:
C>Может есть более толковые решения ?
Если есть возможность, то советую всетаки пользоватся Visitor
я не волшебник, я только учусь!
Re[2]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Arsenicum |
| Дата: | 21.11.08 10:22 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
[покусано]
А>но лучше подумайте над дизайном и не скрещивайте ужа и ежа, желание получить производный тип из базового говорит о неправильном дизайне.
Неужели? А обосновать?
Re[3]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Аноним |
| Дата: | 21.11.08 11:24 |
| Оценка: |
Здравствуйте, Arsenicum, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
A>[покусано]
А>>но лучше подумайте над дизайном и не скрещивайте ужа и ежа, желание получить производный тип из базового говорит о неправильном дизайне.
A>Неужели? А обосновать?
динамиеский полиморфизм используется для работы с разными обеъктами через общий интерфейс, а не для того чтобы можно было хранить разные объекты в одной коллекци. если у вас есть объект базового класса, реализация не должна интересоваться на самом деле это объект базового класса, или объект класса наследника.
ЗЫ на всякий случай напомню, что все вышесказанное имхо.
ЗЫЫ все разы, когда мне приходилось сталкиваться с подобным «понижением по иерархии» это были следствия неправильного построения объектной модели.
ЗЫЫЫ примеров, когда без такого «понижения» нельзя обойтись, я не знаю.
Re[4]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Sergey |
| Дата: | 21.11.08 12:17 |
| Оценка: |
» Аноним 530 » <0@users.rsdn.ru>wrote in message news:3183438@news.rsdn.ru.
> А>>но лучше подумайте над дизайном и не скрещивайте ужа и ежа, желание получить производный тип из базового говорит о неправильном дизайне.
>
> A>Неужели? А обосновать?
>
> динамиеский полиморфизм используется для работы с разными обеъктами через общий интерфейс, а не для того чтобы можно было хранить разные объекты в одной коллекци. если у вас есть объект базового класса, реализация не должна интересоваться на самом деле это объект базового класса, или объект класса наследника.
>
> ЗЫ на всякий случай напомню, что все вышесказанное имхо.
> ЗЫЫ все разы, когда мне приходилось сталкиваться с подобным «понижением по иерархии» это были следствия неправильного построения объектной модели.
0@users.rsdn.ru>
Помимо правильного построения объектной модели иногда играют роль и такие соображения, как практичность. Никто не обещает, что «правильная» (с вашей точки зрения) модель будет удобной и не переусложненной.
> ЗЫЫЫ примеров, когда без такого «понижения» нельзя обойтись, я не знаю.
С программированием окошек сталкиваться, сталбыть, не приходилось? Или там мультиметоды реализовывать?
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена «За заслуги перед Отечеством» является Геннадий Хазанов.
Re[5]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Аноним |
| Дата: | 21.11.08 15:43 |
| Оценка: |
Здравствуйте, Sergey, Вы писали:
S>Помимо правильного построения объектной модели иногда играют роль и такие соображения, как практичность. Никто не обещает, что «правильная» (с вашей точки зрения) модель будет удобной и не переусложненной.
неудобная и переусложненная модель с моей точки зрения как раз неправильна, практичность это конечно хорошо, но явно не во вред поддерживаемости кода, который несут такие «хаки» интерфейса.
S>С программированием окошек сталкиваться, сталбыть, не приходилось? Или там мультиметоды реализовывать?
с окошками слава богу нет, все что видел из более-менее сложных гуев вселяло страх и ужас. мультиметоды реализовывал без динамик каста, как раз способом описанным выше.
Re[6]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Sergey |
| Дата: | 21.11.08 16:07 |
| Оценка: |
» Аноним 530 » <0@users.rsdn.ru>wrote in message news:3183928@news.rsdn.ru.
> S>Помимо правильного построения объектной модели иногда играют роль и такие соображения, как практичность. Никто не обещает, что «правильная» (с вашей точки зрения) модель будет удобной и не переусложненной.
>
> неудобная и переусложненная модель с моей точки зрения как раз неправильна, практичность это конечно хорошо, но явно не во вред поддерживаемости кода, который несут такие «хаки» интерфейса.
0@users.rsdn.ru>
Иногда, в некоторых частях системы, информация о реальном типе просто обязана на время «потеряться». Иначе, придется делать виртуальными все публичные методы всех возможных в данной иерархии интерфейсов. Ну это как если бы из COM выкинуть QueryInterface (который логически является прямым аналогом dynamic_cast’а) и просто реализовать в IUnknown все возможные методы всех объектов.
> S>С программированием окошек сталкиваться, сталбыть, не приходилось? Или там мультиметоды реализовывать?
>
> с окошками слава богу нет, все что видел из более-менее сложных гуев вселяло страх и ужас. мультиметоды реализовывал без динамик каста, как раз способом описанным выше.
На мой взгляд, способ, описанный выше, в плане чистоты концепции «грязнее» динамик каста, поскольку является прямым вытаскиванием потерянной информации о реальном типе объекта. А динамик каст вытаскивает информацию о поддерживаемых объектом интерфейсах.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена «За заслуги перед Отечеством» является Геннадий Хазанов.
Re[4]: полиморфный массив объектов — найти n-ный элемент тип
| От: | chipmunk |
| Дата: | 23.11.08 21:09 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>ЗЫЫ все разы, когда мне приходилось сталкиваться с подобным «понижением по иерархии» это были следствия неправильного построения объектной модели.
А>ЗЫЫЫ примеров, когда без такого «понижения» нельзя обойтись, я не знаю.
разбираю файл. он состоит из одинаковых записей вида:
— идентификатор
— длина
— данные
TLV кажется ещё обзывают (где-то на этом форуме прочитал).
Вот это у меня базовый объект. И соотв. контейнер из этих объектов.
А уже конкретные типы имеют свой интерфейс для разбора данных (чтение/запись значений).
И кажется глупо все свойства впихивать в базовый объект.
А так я dynamic_cast’ом получается могу запросить интерфейс конкретной структуры данных.
Visitor как-то тоже вроде не очень подходит здесь.
Re[2]: полиморфный массив объектов — найти n-ный элемент тип
| От: | chipmunk |
| Дата: | 23.11.08 21:11 |
| Оценка: |
Здравствуйте, IROV. Вы писали:
IRO>Если есть возможность, то советую всетаки пользоватся Visitor
спасибо за совет, я думал над этим, но что-то он не очень тут подходит
здесь я описал мой случай — http://rsdn.ru/forum/message/3185304.1.aspx
Автор: chipmunk
Дата: 24.11.08
Re[5]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Аноним |
| Дата: | 24.11.08 09:12 |
| Оценка: |
Здравствуйте, chipmunk, Вы писали:
C>мой случай:
C>разбираю файл. он состоит из одинаковых записей вида:
C>- идентификатор
C>- длина
C>- данные
C>TLV кажется ещё обзывают (где-то на этом форуме прочитал).
C>Вот это у меня базовый объект. И соотв. контейнер из этих объектов.
C>А уже конкретные типы имеют свой интерфейс для разбора данных (чтение/запись значений).
C>И кажется глупо все свойства впихивать в базовый объект.
базовому объекту достаточно иметь интерфейс для чтения/записи себя в поток, а реализация этого интерфейса зависит от производных объектов.
http://en.wikipedia.org/wiki/Serialization
Re[6]: полиморфный массив объектов — найти n-ный элемент тип
| От: | chipmunk |
| Дата: | 24.11.08 10:16 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>базовому объекту достаточно иметь интерфейс для чтения/записи себя в поток, а реализация этого интерфейса зависит от производных объектов.
А>http://en.wikipedia.org/wiki/Serialization
всё верно, имеет
Re[5]: полиморфный массив объектов — найти n-ный элемент тип
| От: | Sergey |
| Дата: | 24.11.08 16:27 |
| Оценка: |
«chipmunk» <73652@users.rsdn.ru>wrote in message news:3185304@news.rsdn.ru.
> А>ЗЫЫ все разы, когда мне приходилось сталкиваться с подобным «понижением по иерархии» это были следствия неправильного построения объектной модели.
> А>ЗЫЫЫ примеров, когда без такого «понижения» нельзя обойтись, я не знаю.
>
> мой случай:
>
> разбираю файл. он состоит из одинаковых записей вида:
>
> — идентификатор
> — длина
> — данные
>
> TLV кажется ещё обзывают (где-то на этом форуме прочитал).
> Вот это у меня базовый объект. И соотв. контейнер из этих объектов.
> А уже конкретные типы имеют свой интерфейс для разбора данных (чтение/запись значений).
> И кажется глупо все свойства впихивать в базовый объект.
73652@users.rsdn.ru>
Для разбора данных вам нужен ровно один виртуальный метод, принимающий стрим или кусок стрима (не обязательно istream, в зависимости от обстоятельств это может быть, например, дескриптор файла или пара char const*.
Ну и фабрика, которая будет ваши объекты по идентификаторам делать. Заметьте, что на момент создания объекта вам известен его полный тип, что в ряде случаев может сделать касты ненужными.
> А так я dynamic_cast’ом получается могу запросить интерфейс конкретной структуры данных.
> Visitor как-то тоже вроде не очень подходит здесь.
Такую схему обычно применяют если хочется:
1) максимальной независимости частей системы друг от друга (и, как следствие, легкой расширяемости)
2) возможности чтения старой версией нового формата файлов. При этом не понимаемые старой версией данные можно просто игнорировать.
Если нужен только пункт 2, то dynamic_cast вполне уместен. Если пункт 1 — и думать про него забудте. В любом случае, реализация изложенной вами схемы сама по себе dynamic_cast’а не требует, так что применять его или нет — зависит от каких-то других обстоятельств, которые вы здесь пока не изложили.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена «За заслуги перед Отечеством» является Геннадий Хазанов.
Re[6]: полиморфный массив объектов — найти n-ный элемент тип
| От: | chipmunk |
| Дата: | 26.11.08 12:18 |
| Оценка: |
Здравствуйте, Sergey, спасибо за ответ, Вы писали:
S>Для разбора данных вам нужен ровно один виртуальный метод, принимающий стрим или кусок стрима (не обязательно istream, в зависимости от обстоятельств это может быть, например, дескриптор файла или пара char const*.
S>Ну и фабрика, которая будет ваши объекты по идентификаторам делать. Заметьте, что на момент создания объекта вам известен его полный тип, что в ряде случаев может сделать касты ненужными.
это реализовано, фабрика взята из главы 8 книги Александреску «Современное проектирование на С++»
S>Такую схему обычно применяют если хочется:
S>1) максимальной независимости частей системы друг от друга (и, как следствие, легкой расширяемости)
S>2) возможности чтения старой версией нового формата файлов. При этом не понимаемые старой версией данные можно просто игнорировать.
S>Если нужен только пункт 2, то dynamic_cast вполне уместен. Если пункт 1 — и думать про него забудте. В любом случае, реализация изложенной вами схемы сама по себе dynamic_cast’а не требует, так что применять его или нет — зависит от каких-то других обстоятельств, которые вы здесь пока не изложили.
второй пункт пока не актуален.
Но как я доберусь до свойства Y объекта X без dynamic_cast ?
Полиморфизм в C++ и как правильно его реализовать с использованием указателя на void?
Описание вопроса объемное, но сам он скорее всего простой. Суть его такова:
Имеем класс интерфейс, базовый класс, два класса-наследника базового. В интерфейсе также имеем виртуальную ф-ю вывода информации, которая «уточняется» в классах-наследниках.
//класс интерфейс class InterfaceClass < public: InterfaceClass(); ~InterfaceClass(); virtual void output() = 0; >//базовый class Base : public InterfaceClass< public: //тут нужные конструкторы void output(); //выводим a protected: int a; >; //производный class DerivateOne : public Base< public: //тут конструкторы void output(); //выводим b1 и a protected: int b1; >; //производный class DerivateTwo : public Base< public: //тут конструкторы void output(); //выводим b2 и a protected: int b2; >
Далее мы хотим создать массив из объектов типа DerivateOne и DerivateTwo непосредственно в main():
. DerivateOne ArrOne[3]; //массив типа DerivateOne DerivateTwo ArrTwo[3]; //массив типа DerivateTwo //инициализируем элементы массива .
И, собственно, сам вопрос. Пусть у нас есть указатель на void:
void *ptr;
Каким образом пройти по массиву, используя этот самый указатель и адресную арифметику, а именно инкремент (ptr++)?
То бишь вместо:
for (int i = 0; i < 3; i++)< ArrOne[i].output();
Писать что-то в стиле:
ptr = &ArrOne[0] for (int i = 0; i < 3; i++)< ptr->output(); ptr++; >
И, соответственно, после этого ptr будет указывать на элементы массива ArrTwo.
Нужно ли привести void *ptr к типу интерфейса (InterfaceClass*), а уже затем станут доступны операции вида ptr++ и подобные действия с выводом?
Спасибо, что дочитали=)
- Вопрос задан более трёх лет назад
- 2489 просмотров
C++ для начинающих Виртуальные функции Продолжение знакомства Динамический полиморфизм
В продолжении темы начала знакомства с виртуальными функциями пишу этот материал. Несмотря на то, что я описал первопричину использования виртуальных функций, этого явно мало. В литературе для лучшего понимания виртуальных функций используют пример, в котором создается массив объектов. Это не обычный массив объектов, а каждый элемент массива имеет объект различного типа. Вспомним что такое класс. Класс – это пользовательский тип данных. Значит каждый новый класс это новый тип.
Давайте вспомним одно свойство массива. Массив – это набор однотипных данных. Может показаться, что использование наследования и виртуальных функций немного нарушает такое определение. Если размышлять, то можно прийти к мыслям: “Если массив содержит данные только одного типа, то значит в один массив объекты разных типов мне поместить не удастся”. Это совершенно верные мысли. Несмотря на это любой самый обычный массив можно построить таким образом, что элементы, обрабатываемые с помощью него будут иметь различные типы. Может показаться, что я противоречу сам себе, но вовсе нет. Для того, чтобы построить такой массив с элементами различных типов используют массив указателей. Каждый элемент такого массива – это указатель.
Перехожу от слов к делу.
Задача: Создать массив объектов класса млекопитающие
Предположим у нас есть 3 вида млекопитающих и остальные неизвестные нам. Нам известны собака, кот и свинья. Каждое млекопитающее издает собственные звуки. Кот мяукает, собака лает, свинья хрюкает.
Создадим базовый класс – млекопитающие, от которого унаследуем виды млекопитающих и определим для них уникальное поведение (как нам уже известно каждое млекопитающее должно издавать свой звук)
Код C++ Виртуальные функции Динамический полиморфизм
================
/*КЛАСС-РОДИТЕЛЬ*/
class Mammal
public:
virtual void Speak () //Виртуальный метод. Звук неизвестного млекопитающего
/*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
class Dog :public Mammal
public:
void Speak () //Виртуальный метод. Собака лает
>;
/*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
class Cat :public Mammal
public:
void Speak () //Виртуальный метод. Кот мяукает
>;
/*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
class Pig :public Mammal
public:
void Speak () //Виртуальный метод. Свинья хрюкае т
>;
================
Применены приемы наследования. Создано три потомка из основного класса. Каждый потомок – это известное нам млекопитающее
После того как описали нужные действия приступаем к написанию основного кода. Дадим пользователю возможность заносить млекопитающих в массив в том порядке и тех млекопитающих, которых он сам хочет.
Код С++ Виртульные функции Динамический полиморфизм
================
#include
#include
/*КЛАСС-РОДИТЕЛЬ*/
class Mammal
public:
virtual void Speak () < cout / /Виртуальный метод. Звук неизвестного млекопитающего
>;
/*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
class Dog :public Mammal
public:
void Speak () //Виртуальный метод. Собака лает
>;
/*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
class Cat :public Mammal
public:
void Speak () //Виртуальный метод. Кот мяукает
>;
/*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
class Pig :public Mammal
public:
void Speak () //Виртуальный метод. Свинья хрюкает
>;
/*==================*/
void main ()
system ( “CLS” );
Mammal * Array [ 5 ]; //Объявляем массив указателей на класс Млекопитающие
Mammal * ptr ; //Объявили указатель на класс Млекопитающие
int MyWibor ; //Переменная для выбора пользователем
//Небольшое украшательство
cout cout cout cout
//С помощью цикла заполняем массив указателями на объекты
for (int i = 0 ; i < 5 ; i ++)//Пусть млекопитающих пять
cout //Номер текущего млекопитающего
cin >> MyWibor ; //Пользователь вводит число
switch ( MyWibor ) //Основываясь на введенном числе выделяем память для нужного млекопитающего
case 1 :
ptr =new Dog ; //Если один – выделяем память для создания класса Собака
break;
case 2 :
ptr =new Cat ; //Если два – выделяем память для создания класса Кошка
break;
case 3 :
ptr =new Pig ; //Если три – выделяем память для создания класса Свинья
break;
default:
ptr =new Mammal ; //Если что-то другое – выделяем память для создания класса Млекопитающее
break ;
> //switch Выбор сделан
Array [ i ]= ptr ; //Выбор сделан, память выделена, заносим указатель на созданный объект в массив
> //Цикл for завершен
for ( i = 0 ; i < 5 ; i ++) Array [ i ]->Speak (); //Проходим по всему циклу и вызываем метод Speak для каждого элемента
for ( i = 0 ; i < 5 ; i ++) delete Array [ i ]; //Мы выделяли память, значит нужно её освободить.
cin . get ();
cin . get ();
>
================
При запуске этой программы будет предложено ввести число. В зависимости от введенного числа программа определит объект какого типа пользователь стремиться создать. Для объекта выбранного типа выделится необходимая память и указатель, который указывает на адрес созданного объекта будет записан в массив как элемент массива. Благодаря использованию виртуальных функций нам нет нужды задумываться о том, как правильно вызвать метод, который будет описывать звук издаваемый млекопитающим. Другими словами для каждого элемента массива будет вызван именно тот метод, который описан или переопределен в объекте, на который указатель, являющийся элементом массива указывает
Посмотрев и поняв работу примера вы лучше поймете описание полиморфизма: Один класс, множество методов
Основная идея использования полиморфизма : “Независимо от возрастания объемов кода и сложности программы, ко всем объектам, выведенным из базового класса, можно использовать один единственный общий способ доступа для каждого объекта, независимо от того что поведения этих объектов различны”