Программирование >>  Дополнительные возможности наследования 

1 ... 121 122 123 [ 124 ] 125 126 127 ... 265


93 94 95 96 97 98 99

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... Animal constructor... Bird constructor... Pegasus constructor... This pegasus is 2 years old. Pegasus destructor... Bird destructor. . . Animal destructor... Horse destructor... Animal destructor...

В листинге содержится ряд интересных решений. Так, в строках 8-17 объявляется новый класс Animal с переменной-членом itsAge и двумя методами - GetAgeO и SetAgeO.

В строке 25 класс Horse производится от класса Animal. Конструктор класса Horse теперь имеет третий параметр age, который передается в базовый класс Animal. Обратите внимание, что в классе Horse метод GetAgeO не замещается, а просто наследуется.

В строке 46 класс Bird производится от класса Animal. Конструктор этого класса также содержит параметр age, с помощью которого инициализируется базовый класс Animal. Метод GetAgeO также наследуется этим классом без замещения.

Класс Pegasus производится от двух базовых классов Horse и Bird, поэтому с исходным базовым классом Animal он связан двумя линиями наследования. Если для объекта класса Animal будет вызван метод GetAgeO, то для преодоления неопределенности нужно точно указать, к какому базовому классу следует обращаться за этим методом, либо метод GetAgeO следует заместить в классе Pegasus.

В нашем примере программы метод GetAgeO замещается для класса Pegasus таким образом, что в нем явно указывается обращение к аналогичному методу конкретного базового класса.

Замещение функции с добавлением обрашения к методу базового класса позволяет решить две проблемы. Во-первых, преодолевается неопределенность обращения к базовым классам; во-вторых, функцию можно заместить таким образом, что в производном классе при обращении к этой функции будут выполняться дополнительные операции, которых не было в базовом классе. Причем по желанию программиста эти дополнительные операции могут выполняться до вызова функции базового класса или после вызова с использованием значения, возвращенного функцией базового класса.

Конструктор класса Pegasus принимает пять параметров: цвет крылатого коня, его рост (в футах); логическую переменную, которая определяет, мифирует сейчас это животное или мирно пасется на пастбище; число людей, верящих в существование Пегаса,



и возраст животного. В строке 87 конструктор инициализирует переменные, определенные в классе Horse (цвет, рост и возраст). В следующей строке инициализируется часть, относящаяся к классу Bird: цвет, миграции и возраст. Наконец, в строке 89 инициализируется переменная itsNumberBelievers, относящаяся непосредственно к классу Pegasus.

Вызов конструктора класса Horse в строке 87 выполняет операторы, записанные в строке 38. С помощью параметра age конструктор класса Horse инициализирует переменную itsAge, унаследованную классом Horse от класса Animal. Затем инициализируются две переменные-члена класса Horse - itsColor и itsHeight.

Вызов конструктора класса Bird в строке 88 выполняет операторы, записанные в строке 60. И в данном случае параметр age используется для инициализации переменной-члена, унаследованной классом Bird от класса Animal.

Обратите внимание, что значение параметра цвета объекта Pegasus используется для инициализации соответствующих переменных-членов обоих классов. Bird и Horse. Параметр age также инициализирует переменную itsAge обоих этих классов, унаследованную ими от базового класса Animal.

Виртуальное наслеуованне

в листинге 13.5 решалась проблема неопределенности, а именно: от какого базового класса унаследована функция getAgeO в объекте класса Pegasus. Но в действительности этот метод производится от одного общего базового класса Animal.

В С++ существует возможность указать, что мы имеем дело не с двумя одноименными классами, как показано в рис. 13.2, а с одним общим базовым классом (рис. 13.3).


Рис. 13.3. Виртуальное наследование

Для этого класс Animal нужно объявить как виртуальный базовый класс для двух производных классов, Horse и Bird. Класс Animal при этом не подвергается никаким изменениям. В классах Horse и Bird изменения состоят в том, что в их объявлении указывается виртуальность наследования от базового класса Animal. Класс Pegasus изменяется существенно.

Обычно конструктор класса инициализирует только собственные переменные и переменные-члены базового класса. Из этого правила делается исключение, если используется виртуальное наследование. Переменные основного базового класса ини-



циализируются конструкторами не следующих производных от него классов, а тех, которые являются последними в иерархии классов. Поэтому класс Animal инициализируется не конструкторами классов Horse и Bird, а конструктором класса Pegasus. Конструкторы классов Horse и Bird также содержат команды инициализации базового класса Animal, но при создании объекта Pegasus эта инициализация перекрывается конструктором данного класса.

Листинг 13.6 представляет собой программный код из листинга 13.5, переписанный таким образом, чтобы можно было воспользоваться преимуществами виртуального наследования.

йвсвииг. 13.t. Дрнмер нсиржьзпваиня внриуажьнргр весжедовання

2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

Листинг 13.6.

Виртуальное наследование

ftinclude <iostream.h>

typedef int HANDS;

enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ;

class Animal общий базовый класс для двух производных классов horse и bird {

public:

Animal(int);

virtual AnimalO { cout Animal destructor. ..\ n ; }

virtual int GetAgeO const { return itsAge; }

virtual void SetAge(int age) { itsAge = age; } private:

int itsAge; } :

Animal::Animal(int age):

itsAge(age)

cout << Animal constructor...\ n ;

class Horse : virtual public Animal {

public:

Horse(COLOR color, HANDS height, int age);

virtual HorseO { cout << Horse destructor. ..\ n ; }

virtual void Whinny()const { cout Whinny!... ; }

virtual HANDS GetHeightO const { return itsHeight; }

virtual COLOR GetColorO const { return itsColor; } protected:

HANDS itsHeight;

COLOR itsColor; > ;

Horse::Horse(COLOR color, HANDS height, int age): Animal(age),



1 ... 121 122 123 [ 124 ] 125 126 127 ... 265

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика