Список инициализации 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 база: самый производный класс знает лучше всего, что действительно нужно.

Другие вопросы по тегам