Подтвердить что ты не робот

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

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

4b9b3361

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