Заказ вызова конструктора в виртуальном наследовании
class A {
int i;
public:
A() {cout<<"in A def const\n";};
A(int k) {cout<<"In A const\n"; i = k; }
};
class B : virtual public A {
public:
B(){cout<<"in B 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;
}
В этом случае вывод
in A def const
in B const
in C const
Почему это не входит в in A const
`Он должен следовать порядку 1 вызова конструктора arg.
Но что на самом деле происходит при извлечении B из A с использованием виртуального ключевого слова.
Есть еще несколько вопросов
Даже если я удалю ключевое слово virtual в вышеуказанной программе и удалю весь конструктор по умолчанию, он дает ошибку. Итак, зачем ему нужен конструктор def
Ответы
Ответ 1
Конструкторы для виртуальных базовых классов всегда вызывают из самого производного класса, используя любые аргументы, которые он может передать. В вашем случае самый производный класс не указывает инициализатор для A
, поэтому конструктор по умолчанию б.
Ответ 2
Как объяснил ДжеймсКанце, в случае virtual
наследования это самый производный класс, который вызывает конструктор виртуального базового класса. Итак, если вы хотите конструктор A
, который принимает целое число для вызова, вам нужно добавить это в список C
инициализации.
C(int i) : A(i), B(i) {cout<<"in C const\n";}
Для второй части вашего вопроса конструкторы по умолчанию не требуются, но тогда производный класс должен явно вызывать конструктор не по умолчанию, поскольку компилятор не может сделать это для вас в отсутствие конструктора, отличного от стандартного.
#include <iostream>
using namespace std;
class A {
int i;
public:
// A() {cout<<"in A def const\n";};
A(int k) {cout<<"In A const\n"; i = k; }
};
class B : virtual public A {
public:
// B(){cout<<"in B 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;
}
Отпечатает
In A const
in B const
in C const
In A const
in B const
in C def cstr
Ответ 3
Здесь есть два вопроса.
Почему это не входит в const?
Потому что вы используете виртуальное наследование.
Когда вы используете виртуальное наследование, Список инициализации самого производного класса ctor вызывает виртуальный базовый класс ctor.. В этом случае это означает, что конструктор C
вызывает конструктор A
напрямую. Поскольку вы не указали, какой конструктор A
вызывать в списке инициализации C
, вызывается конструктор по умолчанию.
Это фиксируется путем изменения вашей реализации C::C(int)
на:
C(int i) : A(i), B(i) {cout<<"in C const\n";}
Если я удалю ключевое слово virtual в вышеуказанной программе и удалю все по умолчанию он дает ошибку. Итак, зачем это нужно конструктор?
Потому что B
также не определяет, какой A
ctor вызывать, поэтому используется конструктор по умолчанию. Если вы удалите A
def ctor, B
не может быть скомпилирован.