Виртуальное наследование - gcc vs. vc ++ - PullRequest
4 голосов
/ 17 сентября 2009

У меня проблема с 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, компиляция завершится неудачно с сообщением об ошибке «ошибка C2614:« B »: недопустимая инициализация элемента:« Print »не является базой или элементом.»

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

Ответы [ 2 ]

4 голосов
/ 17 сентября 2009

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

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

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

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

0 голосов
/ 17 сентября 2009

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

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

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

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