![]() |
|
Программирование >> Дополнительные возможности наследования
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 itsColor(color),itsHeight(height) cout Horse constructor...\ n ; class Bird : virtual public Animal { public: Bird(C0L0R color, bool migrates, int age); virtual BirdO { cout Bird destructor. ., \ n ; } virtual void ChirpOconst { cout Chirp... ; > virtual void Fly()const { cout I can fly! I can fly! I can fly! ; } virtual COLOR GetColor()const { return itsColor; } virtual bool GetMigrationO const { return itsMigration; } protected: COLOR itsColor; bool itsMigration; } ; Bird::Bird(COLOR color, bool migrates, int age): Animal(age), itsColor(color), itsMigration(migrates) cout Bird constructor...\ n ; class Pegasus : public Horse, public Bird { public: void ChirpOconst { WhinnyO; } Pegasus(COLOR, HANDS, bool, long, int); virtual PegasusO ( cout Pegasus destructor. .. \ n ;) virtual long GetNumberBelieversO const { return ItsNumberBelievers; } virtual COLOR GetColor()const { return Horse::itsColor; } private: long ItsNumberBelievers; Pegasus::Pegasus( COLOR aColor, HANDS height, bool migrates, long NumBelieve, int age): Horse(aColor, height,age), Bird(aColor, migrates,age), Animal(age*2), ItsNumberBelievers(NumBelieve) 90 91 92 93 94 95 96 97 98 99 cout << Pegasus constructor,..\ n ; int main() { Pegasus *pPeg = new Pegasus(Red, 5, true, 10, 2); int age = pPeg->GetAge(); cout << This pegasus is << age << years old.\ n ; delete pPeg; 100: return 0; 101: } Animal constructor... Horse constructor... Bird constructor. . . Pegasus constructor... This pegasus is 4 years old. Pegasus destructor... Bird destructor... Horse destructor... Animal destructor... В строке 25 класс Horse виртуально наследуется от класса Animal, а в строке 45 так же наследуется класс Bird. Обратите внимание, что конструкторы обоих классов по-прежнему инициализируют класс Animal. Но как только создается объект Pegasus, конструктор этого класса заново инициализирует класс Animal, отменяя прежние инициализации. Убедиться в этом вы можете по результату, выводимому программой на экран. При первой инициализации переменной itsAge присваивается значение 2, но конструктор класса Pegasus удваивает это значение. В результате строка 98 профаммы выводит на экран значение 4. Проблемы с неопределенностью наследования метода в классе Pegasus больше не возникает, поскольку теперь метод GetAgeO наследуется непосредственно из класса Animal. В то же время при обращении к методу GetColorO по-прежнему необходимо явно указывать базовый класс, так как этот метод объявлен в обоих классах, Horse и Bird. ПроОлвмы с множественным наследвванивм Хотя множественное наследование дает ряд преимуществ по сравнение с одиночным, многие профаммисты с неохотой используют его. Основная проблема состоит в том, что многие компиляторы С++ все еще не поддерживают множественное наследование; это осложняет отладку программы, тем более что все возможности, реализуемые этим методом, можно получить и без него. Действительно, если вы решите использовать в своей программе множественное наследование, следует учесть, что с отладкой программы могут возникнуть проблемы и чрезмерное усложнение программы, связанное с использованием этого подхода, не всегда оправдывается полученным эффектом. Указание виртуального наследования при объявлении класса Чтобы быть уверенным, что производные классы будут рассматривать исходный базовый класс как единый источник, виртуальность наследования следует указать во всех промежуточных классах. Пример 1: class Horse ; virtual public Animal class Bird : virtual public Animal : class Pegasus : public Horse, public Bird Пример 2: class Schnauzer ; virtual public Dog : . :V / , : class Poodle ; virtual public Oog class Schnoodle : public Schnauzer, public Poodle Рекомендуется Используйте множественное наследование в тех случаях, когда в классе необходимо применять данные и методы, объявленные в разных классах. Используйте виртуальное наследование, чтобы как можно элегантнее обойти проблемы с неопределенностью источника наследования метода или данных. Инициализируйте исходный базовый класс конструктором класса, наиболее удаленного от базового по иерархии классов. Ив рвкомвнууется Не используйте множественное наследование в тех случаях, когда можно обойтись одиночным наследованием. Классы-мануаты Промежуточным решением между одиночным и множественным наследованием классов может быть использование классов-мандатов. Так, класс Horse можно произвести от двух базовых классов - Animal и Displayable, причем последний добавляет только некоторые методы отображения объектов на экране. Классом-мандатом называется класс, открываюший доступ к ряду методов, но не содержащий никаких данных (или, по крайней мере, содержащпй минимальный набор данных). Методы класса-мандата передаются в производные классы с помощью обычного наследования. Единственное отличие классов-мандатов от других классов состоит в том, что они практически не содержат никаких данных. Различие довольно субъективное и отражает только общую тенденцию программирования, сводящуюся к тому, что добавление функциональности классам не должно сопровождаться усложнением программы. Использование классов-мандатов также снижает вероятность возникновения неопределенностей при использовании в производном классе данных, унаследованных из других базовых классов.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |