Заказ вызова конструктора в виртуальном наследовании
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; }
Выход в этом случае равен
in A's def const in B const in C const
Почему это не входит in A const
`Он должен следовать порядку 1 вызова конструктора arg. Но что на самом деле происходит при выводе B из A с использованием виртуального ключевого слова.
- Почему я не могу ссылаться на метод экземпляра при явном вызове конструктора?
- В чем разница между инициализатором объекта и конструктором?
- Параметры конструктора classа scala
- Глубокая копия массива объектов
- Как вы используете конструктор, отличный от стандартного для члена?
Есть еще несколько вопросов
Даже если я удалю ключевое слово virtual в вышеуказанной программе и удалю весь конструктор по умолчанию, он дает ошибку. Итак, зачем ему нужен конструктор def
- Что такое блок инициализации?
- Когда вам нужно явно вызвать конструктор суперclassа?
- У встроенных типов есть стандартные конструкторы?
- Объем переменных в операторах if
- Использование инициализаторов и конструкторов в Java
- C ++: где инициализировать переменные в конструкторе
- Почему Class.newInstance () «злой»?
- Инициализировать защищенные члены родителя с помощью списка инициализации (C ++)
Конструкторы виртуальных базовых classов всегда вызывают из самого производного classа, используя любые аргументы, которые он может передать. В вашем случае самый производный class не указывает инициализатор для A
, поэтому используется конструктор по умолчанию.
Как пояснил JamesKanze , в случае virtual
наследования это самый производный class, который вызывает конструктор виртуального базового classа. Итак, если вам нужен конструктор A
, который принимает целое число, которое нужно вызывать, вам нужно добавить это в список инициализации C
C(int i) : A(i), B(i) {cout<<"in C const\n";}
Для второй части вашего вопроса конструкторы по умолчанию не требуются, но тогда производный class должен явно вызывать конструктор не по умолчанию, поскольку компилятор не может сделать это для вас в отсутствие конструктора, отличного от стандартного.
#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; }
Это печатает
In A const in B const in C const In A const in B const in C def cstr
Здесь есть два вопроса.
Почему это не входит в A const?
Потому что вы используете виртуальное наследование.
Когда вы используете виртуальное наследование, список инициализации процессора ctor самого производного classа непосредственно вызывает ctor виртуального базового classа. , В этом случае это означает, что конструктор C
напрямую вызывает конструктор A
Поскольку вы не указали, какой конструктор должен вызывать в списке инициализации C
вызывается конструктор по умолчанию.
Это фиксируется путем изменения вашей реализации C::C(int)
на:
C(int i) : A(i), B(i) {cout<<"in C const\n";}
Если я удалю ключевое слово virtual в вышеуказанной программе и удалю весь конструктор по умолчанию, он даст ошибку. Итак, зачем нужен конструктор def?
Поскольку B
также не указывает, какой A
ctor вызывать, поэтому используется конструктор по умолчанию. Если вы удалите A
s def ctor, B
не может быть скомпилирован.