Конструкторы классов, полученных в результате множественного наследования
Если класс Pegasus производится от двух базовых классов — Bird и Horse, а в каждом из них объявлены конструкторы со списками параметров, то класс Pegasus инициализирует эти конструкторы. Как это происходит, показано в листинге 13.4.
Листинг 13.4. Создание объектов при множественном наследовании
1: // Листинг 13.4.
2: // Создание обьектов при множественном наследовании
3: #include
4: typedef int HANDS;
5: enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown };
6:
7: class Horse
8: {
9: public:
10: Horse(COLOR color, HANDS height);
11: virtual ~Horse() { cout << "Horse destructor...\n"; }
12: virtual void Whinny()const { cout << "Whinny!... "; }
13: virtual HANDS GetHeight() const { return itsHeight; }
14: virtual COLOR GetColor() const { return itsColor; }
15: private:
16: HANDS itsHeight;
17: COLOR itsColor;
18: };
19:
20: Horse::Horse(COLOR color, HANDSheight):
21: itsColor(color),itsHeight(height)
22: {
23: cout << "Horse constructor...\n";
24: }
25:
26: class Bird
27: {
28: public:
29: Bird(COLOR color, bool migrates);
30: virtual ~Bird() { cout << "Bird destructor...\n"; }
31: virtual void Chirp()const { cout << "Chirp... "; }
32: virtual void Fly()const
33: {
34: cout << "I can fly! I can fly! I can fly! ";
35: }
36: virtual COLOR GetColor()const { return itsColor; }
37: virtual bool GetMigration() const { return itsMigration; }
38:
39: private:
40: COLOR itsColor;
41: bool itsMigration;
42: };
43:
44: Bird::Bird(COLOR color, bool migrates):
45: itsColor(color), itsMigration(migrates)
46: {
47: cout << "Bird constructor...\n";
48: }
49:
50: class Pegasus : public Horse, public Bird
51: {
52: public:
53: void Chirp()const { Whinny(); }
54: Pegasus(COLOR, HANDS, bool,long);
55: ~Pegasus() { cout << "Pegasus destructor...\n";}
56: virtual long GetNumberBelievers() const
57: {
58: return itsNumberBelievers;
59: }
60:
61: private:
62: long itsNumberBelievers;
63: };
64:
65: Pegasus::Pegasus(
66: COLOR aColor,
67: HANDS height,
68: bool migrates,
69: long NumBelieve):
70: Horse(aColor, height),
71: Bird(aColor, migrates),
72: itsNumberBelievers(NumBelieve)
73: {
74: cout << "Pegasus constructor...\n";
75: }
76:
77: int main()
78: {
79: Pegasus *pPeg = new Pegasus(Red, 5, true, 10);
80: pPeg->Fly();
81: pPeg->Whinny();
82: cout << "\nYour Pegasus is " << pPeg->GetHeight();
83: cout << " hands tall and ";
84: if (pPeg->GetMigration())
85: cout << "it does migrate.";
86: else
87: cout << "it does not migrate.";
88: cout << "\nA total of " << pPeg->GetNumberBelievers();
89: cout << " people believe it exists.\n";
90: delete pPeg;
91: return 0;
92: }
Результат:
Horse constructor...
Bird constructor...
Pegasus constructor...
I can fly! I can fly! I can fly! Whinny!...
Your Pegasus is 5 hands tall and it does migrate.
A total of 10 people believe it exists.
Pegasus destructor...
Bird destructor...
Horse destructor...
Анализ:Класс Horse объявляется в строках 7—18. Конструктор этого класса принимает два параметра: один из них — это перечисление, объявленное в строке 5, а второй — новый тип, объявленный с помощью typedef в строке 4. Этот конструктор выполняется в строках 20—24. При этом инициализируется одна переменная-член и на экран выводится сообщение о работе конструктора класса Horse.
В строках 26—42 объявляется класс Bird, конструктор которого выполняется в строках 45—49. Конструктор этого класса также принимает два параметра. Обратите внимание на интересный факт: конструкторы обоих классов принимают перечисления цветов, с помощью которых в программе можно установить цвет лошади или цвет перьев у птицы. В результате, когда вы попытаетесь установить цвет Пегаса, может возникнуть проблема в работе программы, которая обсуждается несколько ниже.
Класс Pegasus объявляется в строках 50—63, а его конструктор — в строках 65—75. Инициализация объекта Pegasus выполняется тремя строками программы. Сначала конструктор класса Horse определяет цвет и рост. Затем конструктор класса Bird инициализируется цветом перьев и логической переменной. Наконец, происходит инициализация переменной-члена itsNumberBelievers, относящейся к классу Pegasus. После всех этих операций вызывается конструктор класса Pegasus.
В функции main() создается указатель на класс Pegasus, который используется для получения доступа к функциям-членам базовых объектов.
В листинге 13.4 оба класса — Horse и Bird — имеют метод GetColor(). В программе может потребоваться возвратить цвет объекта Pegasus, но возникает вопрос: какой из двух унаследованных методов при этом будет использоваться? Ведь методы, объявленные в обоих базовых классах, имеют одинаковые имена и сигнатуры. В результате при компилировании программы возникнет неопределенность, которую необходимо разрешить до компиляции.
Если просто записать:
COLOR currentColor = pPeg->GetColor();
Компилятор покажет сообщение об ошибке Member is ambiguous: ' Horse::GetColor' and ' Bird::GetColor' (Член не определен).
Эту неопределенность можно разрешить, явно обратившись к методу того класса, который вам необходим:
COLOR currentColor = pPeg->Horse::GetColor();
Читать дальше