Problema de diamante: la herencia no múltiple en la rama lateral aún requiere un constructor de clase
-
17-09-2020 - |
Pregunta
Se produjo un problema extraño cuando intenté "resolver" un problema habitual de diamantes de forma habitual, utilizando la herencia virtual:
A
/ \* both virtual
B C
\ /
D
Sin embargo, mi clase base A no tiene constructor de incumplimiento, por lo que iba a llamarlo manualmente desde D. Sin embargo, cuando intento agregar una clase E a este diamante como C-heredado
A
/ \* both virtual
B C
\ / \
D E
Todavía se necesita llamar al constructor de un constructor en E manualmente, es decir, C no es lo que crear una de E aunque no haya múltiples herencias ni diamante A-C-E.
class A
{public:
A (int _N): N(_N) {};
void show()
{cout<<"A"<<N;}
protected:
int N;
};
class B: public virtual A
{ public:
B(int n): A(2*n) {};
void show()
{ cout<<"B"<<N;}
};
class C: public virtual A
{ public:
C(int n): A(3*n) {};
void show()
{ cout<<"C"<<N;}
};
class D: public B,C
{ public:
D(): B(1), C(2), A(3) {};
void show()
{ cout<<"D"<<N;}
};
class E: public virtual C
{ public:
E(): C(1) {};
void show()
{ cout<<"E"<<N;}
};
int main()
{D d; // OK
A *a = &d;
a->show();
E e; // NOT OK, no function A::A() to call in E::E()
A *a2 = &e;
a2->show();
return 0;
}
¿Es posible resolver este problema sin llamar al constructor de A de E? Necesito C para hacerlo correctamente :-).
o es posible no intentar resolver problemas de diamante en absoluto:
A A
| | no virtual at all
B C
\ / \
D E
y aún intento declarar el objeto de la clase D con dos instancias de un, pero informarle al compilador a usar una de C al colar de d cada vez? Cuando intento agregar
using C::A
En la Declaración de D, aún produce un error de base no ambigua a.
Solución
¿Es posible resolver este problema sin llamar al constructor de A de E?Necesito C para hacerlo correctamente: -).
El constructor para la clase más derivado (en este caso, E
) es responsable de llamar al constructor para cualquier clase de base virtual.
El constructor de C
no puede llamar al constructor de A
porque C
no es la clase más derivada.Las clases de base virtual se inicializan antes de Cualquier clase de base directa, por lo que E
debe inicializarse por A
antes de que pueda inicializar C
.
Otros consejos
Sí, las llamadas de constructor de clase base virtual son a diferencia de la función virtual primordial:
- puede anular una función virtual en una clase derivada;
- Usted debe anular una función virtual solo si la función se anula en una de las clases base pero no en otras;
- No se puede anular la lista de iniciales para las clases de base virtual del constructor de clase base.
Esto implica que:
- En lo que respecta a la función de la función virtual, la herencia virtual no afecta a la herencia única en absoluto;
- , pero cuando se trata de llamadas de constructor de clase base, la herencia virtual afecta a cada clase derivada.