Замечание
Предположим, класс зависит от того, в каком порядке будут проинициализированы его компоненты. Вместо того чтобы выводить один класс, наследующий свойства других классов, вы можете объявить зависимый класс в качестве данных-членов нового класса. А новый класс сможет управлять местом и временем инициализации членов зависимого класса.
Использование виртуальных базовых классов
Производные классы и их базовые классы образуют иерархию, которая может достичь невероятной сложности даже в относительно простых программах. Базовый класс может наследоваться одним и более классами, которые, в свою очередь, могут стать базовыми для еще большого числа классов. Следовательно, все эти классы связаны отношениями простого и множественного наследования и, подобно библейским персонажам, один из них порождается другим до тех пор, пока уже никто не сможет сказать, кто к кому относится.
Легко понять, почему возникают конфликты в сложной иерархии классов, особенно когда дело касается множественного наследования. Один из самых распространенных конфликтов возникает, когда производный класс наследует слишком много копий некоторых базовых классов, подобно победителю лотереи, который в один прекрасный день обнаруживает, что у него невероятное количество “троюродных сестер”, о существовании которых он раньше даже не подозревал.
Для демонстрации того, как в производных классах возникают неприятности, связанные с наследованием, ознакомьтесь с классами программы, приведенной в листинге 3.8 .В программе используется сложная взаимосвязь между тремя фиктивными компаниями и трем вымышленными инвесторами: бобом (Bob), Тедом (Ted) и Алисой (Alice). Программа может показаться неудачной шуткой, однако заимствование тесных взаимосвязей из реальной жизни поможет объяснить типичные и зачастую доводящие до белого каления проблемы, возникающие с множественным наследованием.
Листинг 3.8. FRANCH.CPP (множественное наследование и вкладчики)
1: // franch.cpp
2:
3: #include <iosream.h>
4: #include <string.h>
5:
6: class company {
7: private:
8: char *name
9: public:
10: Company(const char *s)
11: name = strdup(s);
12: cout << “In constructor for”;
13: Display();
14: }
15: virtual ??company() {
16: cout << “In destructor for “;
17: Display();
18: delete name;
19: }
20: void Display(void) {cout << name << ‘\n’; }
21: };
22:
23: class Jennys; public Company {
24: public:
25: Jennys(); Company(”Jenny’s”) {}
26: };
27:
28: class McDougles: public Company {
29: public:
30: McDougles(): Company(“McDougles”) {}
31: };
32:
33: class BurgerQueen: public Company {
34: public:
35: BurgerQueen(): Company(“BurgerQueen”) {}
36: };
37:
38: class Bob
39: : public Jennys,
40: public McDougles {
41: };
42:
43: class Bob
44: : public McDougles,
45: public BurgerQueen {
46: };
47:
48: class Alice
49: : public Jennys,
50: public McDougles,
51: public BurgerQueen {
52: };
53:
54: main()
55: {
56: Bob *bobp;
57: Ted *tedp;
58: Alice *alicep;
59:
60: cout << “\nInitializing Bob’s resturant\n”;
61: bobp = new Bob;
62: cout <<” Initializing Ted’s resturant\n”;
63: tedp = new Ted;
64: cout <<” Initializing Alice’s resturant\n”;
65: alicep = new Alice;
66:
67: cout <<”\nDeleting Bob’s resturant\n”;
68: delete bobp;
69: cout <<”Deleting Ted’s resturant\n”;
70: delete tedp;
71: cout <<”Deleting Alice’s resturant\n”;
72: delete alicep;
73:
74: return 0;
75: }
![]() | ![]() | ![]() | |||
Рис. 3.13. Иерархия классов в программе FRANCH.CPP
На рис. 3.13 иллюстрируется родословная классов в FRANCH.CPP. в корне иерархии – класс Company, служащий базовым для трех производных классов – Jennys, McDouglas и BurgerQueen. Каждая из этих “компаний ”-классов выводится из класса Company, и, следовательно, каждый класс наследует член name (строка 8), а также функцию-член Display() (строка 20).
Три предприимчивых инвестора, Боб, Тед и Алиса, объявлены классами (строки 38-52). Класс Bob строит свою кулинарную империю из двух классов Company – Jennys и McDougles. Класс Ted делает себе состояние на McDougles и BurgerQueen.Alice, самая честолюбивая душа из троицы, вкладывает средства сразу в три класса Company – Jennys, McDougles и BurgerQueen. Когда вы запустите программу то, увидите сообщения, рапортующие, какие конструкторы и деструкторы и когда был запущены, как они инициализировали и очищали три объекта классов, по одному на каждого вкладчика (строки 56-58).