Форум программистов, компьютерный форум CyberForum.ru

Ромбовидное наследование. Конструктор внука. - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.93
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
13.04.2012, 16:41     Ромбовидное наследование. Конструктор внука. #1
если хотите, можете почитать код - он довольно объёмный...но однотипный
C++
1
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
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
 
class chipset
{
    short *USB_number;//[0] - usb2 / [1] - usb3
    
public:
    chipset(short usb2, short usb3)
    {
        cout<<"Я МУЖИК"<<endl;
        
        USB_number = new short[2];
        USB_number[0] = usb2;
        USB_number[1] = usb3;
    }
    
    chipset(chipset &chip)
    {
        
        
        USB_number = new short[2];
        USB_number[0] = chip.USB_number[0];
        USB_number[1] = chip.USB_number[1];
    }
 
    chipset()
    {
        
        
        USB_number = new short[2];
        USB_number[0] = 4;
        USB_number[1] = 0;
    }
 
    void operator = (chipset &chip)
    {
        //cout<<"Я МУЖИК"<<endl;
        
        USB_number[0] = chip.USB_number[0];
        USB_number[1] = chip.USB_number[1];
    }
 
    void print()
    {
        cout<<endl<<"Вывод конфигурации"<<endl;
        cout<<"\tUSB2 \t-\t"<<USB_number[0]<<" шт."<<endl;
        cout<<"\tUSB3 \t-\t"<<USB_number[1]<<" шт."<<endl;
    }
 
    ~chipset()
    {
        delete [] USB_number;
    }
};
 
class chipsetP : virtual public chipset
{
    short* Multi;
    bool SLI_CF_enable;
 
protected:
 
    void _print()
    {
        cout<<"\tНастройки ЦП:"<<endl;
        cout<<"\t\tядро1 \t-\tx"<<Multi[0]<<endl;
        cout<<"\t\tядро2 \t-\tx"<<Multi[1]<<endl;
        if (SLI_CF_enable)
            cout<<"\tSLI/CrossFire \t-\t включён"<<endl;
        else
            cout<<"\tSLI/CrossFire \t-\t выключен"<<endl;
    }
 
    void _operatorEQ(chipsetP &chP)
    {
        Multi[0] = chP.Multi[0];
        Multi[1] = chP.Multi[1];
        SLI_CF_enable = chP.SLI_CF_enable;
    }
 
public:
    chipsetP(short usb2, short usb3, short core1, short core2, bool SC):chipset(usb2, usb3)
    {
        Multi = new short[2];
        Multi[0] = core1;
        Multi[1] = core2;
        SLI_CF_enable = SC;
    }
 
    chipsetP(chipsetP & cp):chipset(cp)
    {
        Multi = new short[2];
        Multi[0] = cp.Multi[0];
        Multi[1] = cp.Multi[1];
        SLI_CF_enable = cp.SLI_CF_enable;
    }
 
    chipsetP()
    {
        Multi = new short[2];
        Multi[0] = 30;
        Multi[1] = 30;
    }
 
    void print()
    {
        chipset::print();
        _print();
    }
 
    void operator = (chipsetP &chP)
    {
        chipset::operator=(chP);
        _operatorEQ(chP);
    }
    
    ~chipsetP()
    {
        delete [] Multi;
    }
};
 
class chipsetH : virtual public chipset
{
    bool Quick_Sync;
    short *HDGraph;
 
protected:
    void _print()
    {
        cout<<"\tВстроенное граф ядро:"<<endl;
        cout<<"\t\tчастота \t-\t"<<HDGraph[0]<<" Мгц"<<endl;
        cout<<"\t\tкол-во потоков \t-\t"<<HDGraph[1]<<" шт."<<endl;
        if (Quick_Sync)
            cout<<"\t\tQuick_Sync \t-\t включён"<<endl;
        else
            cout<<"\t\tQuick_Sync \t-\t выключен"<<endl;
    }
    void _operatorEQ(chipsetH &chH)
    {
        HDGraph[0] = chH.HDGraph[0];
        HDGraph[1] = chH.HDGraph[1];
        Quick_Sync = chH.Quick_Sync;
    }
 
public:
    chipsetH()
    {
        HDGraph = new short[2];
        HDGraph[0] = 1500;
        HDGraph[1] = 12;
        Quick_Sync = true;
    }
 
    chipsetH(chipsetH &cH) : chipset(cH)
    {
        HDGraph = new short[2];
        HDGraph[0] = cH.HDGraph[0];
        HDGraph[1] = cH.HDGraph[1];
        Quick_Sync = cH.Quick_Sync;
    }
 
    chipsetH(short USB2, short USB3, short Hhz, short streams, bool Quick_Sync_) : chipset(USB2, USB3)
    {
        HDGraph = new short[2];
        HDGraph[0] = Hhz;
        HDGraph[1] = streams;
        Quick_Sync = Quick_Sync_;
    }
 
    void print()
    {
        chipset::print();
        _print();
    }
 
    void operator = (chipsetH& chH)
    {
        _operatorEQ(chH);
        chipset::operator=(chH);
    }
    
    ~chipsetH()
    {
        delete [] HDGraph;
    }
 
 
};
 
class chipsetZ : public chipsetH, public chipsetP
{
    bool *video_mode;
    bool Smart_Response;
 
protected:
    void _print()
    {
        cout<<"\tПодключённые мониторы:"<<endl;
        if(video_mode[0] == true)
            cout<<"\t\tмонитор обнаружен в дескретной карте"<<endl;
        else
            cout<<"\t\tслот дискретной карты пуст"<<endl;
 
        if(video_mode[1] == true)
            cout<<"\t\tмонитор обнаружен во встроенной карте"<<endl;
        else
            cout<<"\t\tслот встроенной карты пуст"<<endl;
 
        if (Smart_Response)
            cout<<"\tХэширование HDD включено"<<endl;
        else
            cout<<"\tХэширование HDD выключено"<<endl;
    }
 
public:
    chipsetZ(chipsetZ &chZ)
    {
        video_mode = new bool[2];
        for(int i=0; i<2; ++i)
            video_mode[i] = chZ.video_mode[i];
    }
 
    chipsetZ(short USB2, short USB3, short core1, short core2, bool CF, short Hhz, short streams, bool Quick_Sync_, bool card_e, bool int_e):chipset(USB2, USB3)
    {
        video_mode = new bool[2];
        video_mode[0] = card_e;
        video_mode[1] = int_e;
    }
 
    void print()
    {
        chipset::print();
        chipsetP::_print();
        chipsetH::_print();
        _print();
    }
    
    ~chipsetZ()
    {
        delete [] video_mode;
    }
};
проблема в конструкторах внука...(chipsetZ)
теперь более конктретно:
C++
1
chipsetZ(short USB2, short USB3, short core1, short core2, bool CF, short Hhz, short streams, bool Quick_Sync_, bool card_e, bool int_e):chipset(USB2, USB3)
у меня проблема в понимании самого процесса вызовов конструкторов:
я думаю так:
при такой записи сначало вызовется конструктор по умолчанию предка chipsetH(который в свою очередь вызовет конструктор по умолчанию для "дедушки" chipset), потом конструктор по умолчанию для chipsetP (который тоже вызовет дедушку по умолчанию), потом вызовется конструктор дедушки с параметрами ЮЗБ2 и ЮЗБ3.
итого: получили вызов конструктора дедушки 3 раза?
выход виже в следующем: добавить в протектед секции папы и мамы (H и P) спец конструкторы, которые соответствуют уникальным полям. Но тогда возникают ещё вопросы...ведь я же не смогу вызвать конструкторы папы и мамы (в протектет секциях папы и мамы), не вызвав конструктор деда? Он же по умолчанию вызовется...
надеюсь, мои слова поймёте...пытался как можно более подробно расписать
спасибо
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.04.2012, 16:41     Ромбовидное наследование. Конструктор внука.
Посмотрите здесь:

Наследование и конструктор. C++
C++ Наследование(Не вызывается конструктор)
Доступ внука к Protected C++
Ромбовидное наследование. Деструкторы. C++
C++ Наследование, конструктор класса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
13.04.2012, 21:47     Ромбовидное наследование. Конструктор внука. #2
Допустим, есть класс Base, Derived1: public virtual Base, Derived2: public virtual Base и наконец Final: public virtual Derived1, public virtual Derived2
При вызове конструктора Final он вызывает конструктор Derived1, вызывающий конструктор Base. Затем вызывается конструктор Derived2, который в данном случае не вызывает конструктор Base, поскольку этот подобъект считается уже сконструированным.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
13.04.2012, 23:51  [ТС]     Ромбовидное наследование. Конструктор внука. #3
Хм...хорошо...но, как я понял, это касается только конструкторов по умолчанию
то есть так:
при вызове любого конструктора Final, вызывается конструктор по умолчанию для Derived1 и Derived2, если не написано обратного, к тому же вызывается конструктор по умолчанию для Base - один раз.
но дело в том, что вызов у меня - это
C++
1
chipsetZ(short USB2, short USB3, short core1, short core2, bool CF, short Hhz, short streams, bool Quick_Sync_, bool card_e, bool int_e):chipset(USB2, USB3)
то есть я ЯВНО вызываю конструктор Base, который не является конструктором по умолчанию.
К тому же, я планирую написать что-то типо такого
C++
1
chipsetZ(short USB2, short USB3, short core1, short core2, bool CF, short Hhz, short streams, bool Quick_Sync_, bool card_e, bool int_e):chipset(USB2, USB3), chipsetH(...), chipsetP(...)
причём конструкторы chipsetH(...) и chipsetP(...) тоже вызывают не дефолнтный констуктор chipset? например
C++
1
chipsetH(short USB2, short USB3, short Hhz, short streams, bool Quick_Sync_) : chipset(USB2, USB3)
как будет происходить вызов в этом случаи?
и как тогда добиться, чтобы строка примерного вида
C++
1
chipsetZ(short USB2, short USB3, short core1, short core2, bool CF, short Hhz, short streams, bool Quick_Sync_, bool card_e, bool int_e):chipset(USB2, USB3), chipsetH(...), chipsetP(...)
вызывала 1 раз конструктор деда, и 1 раз конструкторы для папы и мамы. Загвоздка в том, что я явно в конструкторе мамы и папы вызываю конструктор деда.
C++
1
chipsetH(short USB2, short USB3, short Hhz, short streams, bool Quick_Sync_) : chipset(USB2, USB3)
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
14.04.2012, 10:16     Ромбовидное наследование. Конструктор внука. #4
Это относится к вызовам любого конструктора второго и последующих родителей, в том числе и к тем, что явно вызывают конструктор "дедушки". Эти вызовы игнорируются, потому что "дедушка" считается уже сконструированным.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
14.04.2012, 12:14  [ТС]     Ромбовидное наследование. Конструктор внука. #5
Спасибо
taras atavin
14.04.2012, 13:40
  #6

Не по теме:

А чем бывает вызвано ромбовидное наследование? Каковы преимущества и недостатки? Каковы альтернативы?

Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
14.04.2012, 15:00     Ромбовидное наследование. Конструктор внука. #7
Цитата Сообщение от taras atavin Посмотреть сообщение
А чем бывает вызвано ромбовидное наследование? Каковы преимущества и недостатки? Каковы альтернативы?
Вообще ромбовидное наследование - штука очень сомнительная и веский повод пересмотреть проект программы. Я так сходу не могу смоделировать случай, в котором его использование было бы оправдано. Может, такие случаи и встречаются, но очень редко. Мне в моей практике не встречались ни разу.
Альтернативы в порядке предпочтительности:
а) композиция, необходимые классы включаются в результирующий в качестве членов
б) микс-ины: класс наследует от узкоспециализированных "примесей", добавляющих узкое подмножество свойств
в) обычное множественное наследование от классов, не имеющих общих предков
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
14.04.2012, 17:07  [ТС]     Ромбовидное наследование. Конструктор внука. #8
Самый обычный пример, который всем всегда приводят -это:
есть ПЕРСОНА
СТУДЕНТ и ПРЕПОДОВАТЕЛЬ - наследники
а их общий предок АСПИРАНТ вбирает в себя всё лучшее - то есть их общий потомок.
вот и ромбовидное наследование
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.04.2012, 17:16     Ромбовидное наследование. Конструктор внука. #9
Цитата Сообщение от IcyWind Посмотреть сообщение
Самый обычный пример, который всем всегда приводят -это:
есть ПЕРСОНА
СТУДЕНТ и ПРЕПОДОВАТЕЛЬ - наследники
а их общий предок АСПИРАНТ
Это как интересно аспирант может быть предком студента? Если A - предок B, то всякий экземпляр B - одновременно экземпляр A, но не наоборот. Студент может не быть аспирантом и чаще всего именно так и бывает. Да и преподавать может не быть аспирантом, а вот аспирант обязан преподавать, то есть всякий аспирант - преподаватель. Таким образом, в ООП преподаватель - предок аспиранта, а не потомок, а студент с ними ни каким наследованием не связан, так как и студенты обычно не преподают, и преподаватели обычно не являются студентами.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
14.04.2012, 17:20  [ТС]     Ромбовидное наследование. Конструктор внука. #10
ну видно же, что очепятка...
прочтите внимательно строчку
"их общий предок АСПИРАНТ вбирает в себя всё лучшее - то есть их общий потомок."

Самый обычный пример, который всем всегда приводят -это:
есть ПЕРСОНА
СТУДЕНТ и ПРЕПОДОВАТЕЛЬ - наследники
а их общий наследник АСПИРАНТ вбирает в себя всё лучшее - то есть их общий потомок.
вот и ромбовидное наследование
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.04.2012, 20:25     Ромбовидное наследование. Конструктор внука. #11
Аспирант чаще всего не является студентом, а студент - аспирантом. Сами возможности аспиранту не быть студентом, а студенту - не быть аспирантом вместе исключает отношение наследования между этими классами, так как всякий экземпляр потомка одновременно должен быть экземпляром всех его предков. Студент чаще всего не преподаёт, то есть не является преподавателем, а преподаватель чаще всего не является студентом. Опять наследование исключено. Аспирант - общий потомок преподавателя и обучающегося. Но студент не является ни предком, ни потомком ни одного из них. Именно это критерий различия между наследованием и случайной общностью атрибутов/методов: если всякий экземпляр одного класса одновременно является экземпляром другого, то наследование имеет место. Но стоит ли учитывать все отношения в модели? И почему? Какие есть преимущества и недостатки?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.04.2012, 09:37     Ромбовидное наследование. Конструктор внука.
Еще ссылки по теме:

Конструктор. Наследование. Список инициализации C++
Наследование, перегрузка, конструктор C++
Наследование и конструктор с аргументами по умолчанию C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
15.04.2012, 09:37     Ромбовидное наследование. Конструктор внука. #12
Цитата Сообщение от taras atavin Посмотреть сообщение
Но стоит ли учитывать все отношения в модели?
Разумеется, в модели стоит учитывать только те отношения, которые важны для решения поставленной задачи.

Цитата Сообщение от taras atavin Посмотреть сообщение
Студент чаще всего не преподаёт, то есть не является преподавателем, а преподаватель чаще всего не является студентом. Опять наследование исключено.
Это совершенно справедливо. В данном случае гораздо корректнее выделить "обучаемого" и "обучающего" в отдельные классы-примеси, и наследовать всю троицу от "персоны", добавляя нужный набор свойств:
C++
1
2
3
4
5
6
7
class Person {public: explicit Person(const std::string& name);};
class Educable {public: void BeLearned();};
class Educator {public: void Educate(Educable& student);};
 
class Student: public Person, public Educable {/*...*/};
class Teacher: public Person, public Educator {/*...*/};
class Postgraduate: public Person, public Educable, public Educator {};
Так это выглядит в простейшем виде. В более реальных задачах мы скорее всего реализуем динамически изменяющийся набор обязанностей у персоны: студент может со временем стать аспирантом, а аспирант - преподавателем.
Yandex
Объявления
15.04.2012, 09:37     Ромбовидное наследование. Конструктор внука.
Ответ Создать тему
Опции темы

Текущее время: 12:09. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru