Заказ вызова конструктора в виртуальном наследовании

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 с использованием виртуального ключевого слова.

Есть еще несколько вопросов

Даже если я удалю ключевое слово virtual в вышеуказанной программе и удалю весь конструктор по умолчанию, он дает ошибку. Итак, зачем ему нужен конструктор def

Конструкторы виртуальных базовых 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 не может быть скомпилирован.

  • Виртуальный вызов участника в конструкторе
  • Вызов конструктора базового classа из конструктора производного classа
  • Зачем «шагать» в конструкторе System.Drawing.Bitmap быть кратным 4?
  • Когда выполняется конструктор пользовательского атрибута?
  • Как инициализировать значения HashSet по построению?
  • Включена ли новая функция инициализации члена C ++ 11 при объявлении, что списки инициализации устарели?
  • Почему элементы const должны быть инициализированы в инициализаторе конструктора, а не в его теле?
  • Вызов виртуальной функции из конструктора
  • Соответствуют ли скобки после имени типа с новым?
  • Статические методы фабрики против экземпляров (обычных) конструкторов?
  • Как использовать конструкторы базового classа и оператор присваивания в C ++?
  • Давайте будем гением компьютера.