Список инициализации C++ игнорирует вызов конструктора родительского класса
В следующем коде построение класса C начинается с инициализации A, затем B1, а затем B2 и, наконец, класса C. Однако при инициализации B1 и B2 отладчик игнорировал инициализацию A(1) и A(2) (которые появляются в списке инициализации B1 и B2 в этом порядке), но не игнорировал инициализацию B2(3) в списке инициализации C.
Это почему?
Заранее спасибо.
Вот код:
struct A {
int i;
A() { i = 0; }
A(int _i) : i(_i) {}
virtual void f() { cout << i; }
};
struct B1 : virtual A {
B1() : A(1) { f(); }
void f() { cout << i+10; }
};
struct B2 : virtual A {
B2(int i) : A(2) { f(); }
};
struct C : B1, B2 {
C() : B2(3) {}
};
int _tmain(int argc, _TCHAR* argv[])
{
C* c = new C();
return 0;
}
2 ответа
Именно так компилятор избегает "алмаза смерти". Если вызывать A(1) и A(2), это означает, что была инициализация дубликата базового класса, это цель виртуального наследования - удалить неоднозначные общие базовые элементы.
За virtual
оснований, наиболее производный класс должен предоставить аргументы конструктора, например:
struct C
: B1, B2 {
C()
: A(17)
, B2(3) {}
};
Если самый производный класс не упоминает virtual
база в своем списке инициализатора, конструктор по умолчанию virtual
используется база (если ее нет, это ошибка).
Это делается для того, чтобы избежать двусмысленности относительно того, какие из производных классов должны предоставлять аргументы конструктора для общего virtual
база: самый производный класс знает лучше всего, что действительно нужно.