En un constructor de clase abstracto, ¿por qué necesito llamar a un constructor de una base virtual que nunca llamará?
Me enfrento a la conocida situación del diamante "temido":
A
/ \
B1 B2
\ /
C
|
D
La claseA
tiene, dice el constructorA::A(int i)
. También quiero prohibir una instanciación predeterminada de unA
así que declaro el constructor predeterminado deA
comoprivate
.
Las clasesB1
yB2
se derivan virtualmente deA
y tener algunos constructores y unaprotected
Constructor predeterminado.
[editar] Los constructores deB1
yB2
no llame al constructor predeterminado deA
. [reeditar] Los constructores predeterminados deB1
yB2
no llame al constructor predeterminado deA
ya sea. [reeditar] [editar]
La claseC
es una clase abstracta y tiene algunos constructores que no llaman a ninguno de losA
, B1
oB2
constructores
En la claseD
Llamo al constructorA::A(i)
y algún constructor deC
.
Entonces, como se esperaba, cuandoD
es creado, primero crea unA
para resolver el temido problema del diamante, entonces creaB1
, B2
yC
. Por lo tanto, no hay llamada del constructor predeterminado deA
enB1
, B2
yC
porque si existiera, crearía muchas instancias deA
.
El compilador rechaza el código porque el constructor predeterminado deA
esprivate
. Si lo configuro aprotected
Se compila.
Lo que no entiendo es que cuando ejecuto el código, el constructor predeterminado deA
nunca se llama (como debería ser). Entonces, ¿por qué el compilador no me permite configurarlo comoprivate
?
[editar] bien, escribiré un ejemplo ... pero duele ;-)
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);
}
El compilador dice que en constructor deC
, A::A()
es privado. Estoy de acuerdo con esto, pero comoC
es una clase abstracta, no se puede instanciar como un objeto completo (pero se puede instanciar como un subobjeto de clase base, instanciando unD
) [editar]
Agregué la etiqueta 'language-lawer' por recomendación de alguien.