Виртуальное наследование-gcc против vc++


У меня есть проблема с Visual Studio 2008, касающаяся виртуального наследования.

Рассмотрим следующий пример:

#include<iostream>

class Print {
    public:

    Print (const char * name) {
        std::cout << name << std::endl;
    }
};

class Base : public virtual Print {
    public:

    Base () : Print("Base") {}
};

class A : public Base {
    public:

    A () : Print("A") {}
};

class B : public A {
    public:

    B () : Print("B") {}
};

int main (int argc, char** argv) {
    A a; // should print "A"
    B b; // should print "B"
    return 0;
}

Этот код прекрасно компилируется, если я использую gcc на своей машине linux. Но если я попытаюсь построить то же самое на windows с Visual Studio, компиляция завершится неудачей с сообщением об ошибке "error C2614: 'B': illegal member initialization: 'Print' не является базой или членом."

Почему это не работает?

2 4

2 ответа:

Из стандартного [класса.база.init]: "если mem-initializer-id не называет нестатический элемент данных класса конструктора или прямую или виртуальную базу этого класса, то mem-initializer неправильно сформирован."

Очевидно, gcc интерпретирует ваш случай как юридический, поскольку Print является не прямой, а виртуальной базой B, однако MSVC 2008 не видит Print как виртуальную базу B-только виртуальную базу невиртуальной базы. (Кстати, Ваш пример компилируется на VS2005, так что это удивительно изменение в поведении.)

Я склоняюсь к интерпретации gcc Как правильной (в противном случае фраза "прямая основа" была бы достаточной).

Чтобы обойти эту проблему, вы можете вывести B практически из Print. Поскольку Print уже является виртуальной базой A, это не оказывает никакого общего влияния на макет класса или количество подобъектов базового класса Print.

Какую версию Visual Studio вы используете? Код, который вы опубликовали, прекрасно работает для меня с VC 9 (в частности, 15.00.21022.08) и VC 6, а также с несколькими другими компиляторами.

Вы уверены, что по ошибке class B не выглядит так в Visual Studio:

class B {  //  note: no base class
    public:

    B () : Print("B") {}
};