В абстрактном конструкторе класса, почему мне нужно вызывать конструктор виртуальной базы, который никогда не будет вызван?
Я сталкиваюсь с хорошо известной «страшной» алмазной ситуацией:
A
/ \
B1 B2
\ /
C
|
D
КлассA
имеет, скажем, конструкторA::A(int i)
, Я также хочу запретить создание по умолчаниюA
поэтому я объявляю конструктор по умолчаниюA
какprivate
.
КлассыB1
а такжеB2
практически получены изA
и есть некоторые конструкторы иprotected
конструктор по умолчанию.
[править] КонструкторыB1
а такжеB2
не вызывайте конструктор по умолчаниюA
, [reedit] Конструкторы по умолчаниюB1
а такжеB2
не вызывайте конструктор по умолчаниюA
или. [редактировать] [редактировать]
КлассC
является абстрактным классом и имеет некоторые конструкторы, которые не вызывают ни одного изA
, B1
или жеB2
Конструкторы.
В классеD
Я вызываю конструкторA::A(i)
и какой-то конструкторC
.
Так, как и ожидалось, когдаD
создается, он сначала создаетA
чтобы решить проблему страшного алмаза, то это создаетB1
, B2
а такжеC
, Поэтому нет вызова конструктора по умолчаниюA
вB1
, B2
а такжеC
потому что, если бы было, это создало бы много случаевA
.
Компилятор отклоняет код, потому что конструктор по умолчаниюA
являетсяprivate
, Если я установлю его наprotected
это компилируется.
Что я не понимаю, так это то, что когда я запускаю код, конструктор по умолчаниюA
никогда не вызывается (как и должно быть). Так почему же компилятор не позволяет мне установить его какprivate
?
[править] хорошо, я напишу пример ... но это больно ;-)
class A{
public:
A(int i):i_(i){};
virtual ~A(){};
protected:
int i_;
private:
A():i_(0){};/*if private => compilation error, if protected => ok*/
};
class B1: public virtual A{
public:
B1(int i):A(i){};
virtual ~B1(){};
protected:
B1():A(0){};
};
class B2: public virtual A{
public:
B2(int i):A(i){};
virtual ~B2(){};
protected:
B2():A(0){};
};
class C: public B1, public B2{
public:
C(int j):j_(j){};
virtual ~C()=0;
protected:
int j_;
};
C::~C(){};
class D: public C{
public:
D(int i,int j):A(i),C(j){};
~D(){};
};
int main(){
D d(1,2);
}
Компилятор говорит, что в конструктореC
, A::A()
это личное. Я согласен с этим, но какC
является абстрактным классом, его нельзя создать как завершенный объект (но его можно создать как подобъект базового класса, создав экземплярD
). [редактировать]
Я добавил тег `language-lawer 'по чьей-то рекомендации.