4

我对 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;
}

如果我在我的 linux 机器上使用 gcc,这段代码编译得很好。但是,如果我尝试使用 Visual Studio 在 Windows 上构建相同的内容,则编译失败并显示错误消息“错误 C2614:'B':非法成员初始化:'Print' 不是基础或成员。”

为什么这不起作用?

4

2 回答 2

4

来自标准 [class.base.init]:“除非 mem-initializer-id 命名构造函数类的非静态数据成员或该类的直接或虚拟基类,否则 mem-initializer 格式错误。”

显然,gcc 将您的案例解释为合法的,因为Print它是非直接但虚拟的基础B,但是 MSVC 2008 并不认为Print是的虚拟基础B- 只是非虚拟基础的虚拟基础。(顺便说一句,您的示例在 VS2005 上编译,所以这是一个令人惊讶的行为变化。)

我倾向于认为gcc解释是正确的(否则“直接基础”的措辞就足够了)。

要解决此问题,您B实际上可以从Print. 由于Print它已经是一个虚拟基础,因此对类布局或基类子对象A的数量没有任何整体影响。Print

于 2009-09-17T07:31:57.773 回答
0

您使用的是什么版本的 Visual Studio?您发布的代码对我来说适用于 VC 9(特别是 15.00.21022.08)、VC 6 以及其他一些编译器。

您确定class B在 Visual Studio 中错误地看起来不像这样:

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

    B () : Print("B") {}
};
于 2009-09-17T07:35:23.937 回答