Orden de llamada de constructor en herencia virtual

class A { int i; public: A() {cout<<"in A's def const\n";}; A(int k) {cout<<"In A const\n"; i = k; } }; class B : virtual public A { public: B(){cout<<"in B's def const\n";}; B(int i) : A(i) {cout<<"in B const\n";} }; class C : public B { public: C() {cout<<"in C def cstr\n";} C(int i) : B(i) {cout<<"in C const\n";} }; int main() { C c(2); return 0; } 

El resultado en este caso es

 in A's def const in B const in C const 

¿Por qué esto no está entrando in A const

`Debería seguir el orden de 1 arg llamada de constructor. Pero, en realidad, lo que está sucediendo al derivar B de A es usar una palabra clave virtual.

Hay pocas preguntas más

Incluso si elimino la palabra clave virtual en el progtwig anterior y elimino todo el constructor predeterminado, da error. Entonces, ¿por qué necesita el constructor de def?

Los constructores de clases base virtuales siempre se invocan desde la clase más derivada, utilizando cualquier argumento que pueda pasar. En su caso, la clase más derivada no especifica un inicializador para A , por lo que se utiliza el constructor predeterminado.

Como JamesKanze ha explicado , en el caso de virtual herencia virtual , es la clase más derivada que llama al constructor de la clase base virtual. Por lo tanto, si desea que el constructor de A tome un número entero, debe agregarlo a la lista de inicialización de C

 C(int i) : A(i), B(i) {cout<<"in C const\n";} 

Para la segunda parte de su pregunta, los constructores por defecto no son necesarios, pero luego la clase derivada debe llamar explícitamente al constructor no predeterminado, ya que el comstackdor no puede hacer eso por usted en ausencia de un constructor no predeterminado.

 #include  using namespace std; class A { int i; public: // A() {cout<<"in A's def const\n";}; A(int k) {cout<<"In A const\n"; i = k; } }; class B : virtual public A { public: // B(){cout<<"in B's def const\n";}; B(int i) : A(i) {cout<<"in B const\n";} }; class C : public B { public: C() : A(42), B(42) {cout<<"in C def cstr\n";} C(int i) : A(i), B(i) {cout<<"in C const\n";} }; int main() { C c(2), c2; return 0; } 

Esto se imprime

 In A const in B const in C const In A const in B const in C def cstr 

Hay dos preguntas aquí.

¿Por qué esto no está entrando en A const?

Porque estás usando herencia virtual.

Cuando utiliza herencia virtual, la lista de inicialización del ctor de la clase derivada invoca directamente el ctor de la clase base virtual. . En este caso, eso significa que el constructor de C llama directamente al constructor de A Como no ha especificado qué constructor A para llamar en la lista de inicialización de C , se llama al constructor predeterminado.

Esto se soluciona al cambiar su implementación de C::C(int) a:

 C(int i) : A(i), B(i) {cout<<"in C const\n";} 

Si elimino la palabra clave virtual en el progtwig anterior y elimino todo el constructor predeterminado, se produce un error. Entonces, ¿por qué necesita el constructor de def?

Porque B tampoco especifica a qué Actor llamar, por lo que se usa el constructor predeterminado. Si elimina el deflector de A, B no se puede comstackr.