C ++虚拟方法的虚拟继承

时间:2015-06-23 15:22:05

标签: c++ inheritance virtual virtual-inheritance

struct A {
    virtual void foo() { std::cout << "a";};
};

struct B:public virtual A {
    void foo() { std::cout << "b";}
};

struct C:public virtual A {
    void foo() { std::cout << "c";}
};

struct D:public B, public C {

};
int main() {
    return 0;
}

因此编译时这个给出了以下错误:

 \main.cpp:16:8: error: no unique final overrider for 'virtual void A::foo()' in 'D'
 struct D:public B, public C {

如果我们将B和C结构的继承非虚拟化,代码正在编译恰到好处而没有任何错误(但当然如果我们调用dd.foo会发生错误( ))。那有什么区别?为什么我们在虚拟地继承我们的类时会出现错误,如果我们直接进行操作就没有错误?

1 个答案:

答案 0 :(得分:4)

使A 虚拟基类BC确保D只包含一个A子对象 [1] 。为此,BC都为foo [2] 提供了最终覆盖,两者都由D 继承[2] ,因此Dfoo的两个最终覆盖,使程序格式错误 [2]

A 虚拟基类BC时,D将包含两个不同的A子对象 [1] 。这些子对象中的每一个都将拥有自己继承的foo [2] 的最终覆盖。

[1]:N4140§10.1[class.mi] / 4:

  

不包含关键字virtual的基类说明符指定非虚基类。包含关键字virtual的基类说明符指定虚拟基类。对于每个不同的事件   在最派生类的类点阵中的非虚基类,最派生的对象应包含该类型的相应的不同基类子对象。对于指定为virtual的每个不同的基类,最派生的对象应包含该类型的单个基类子对象。

[2]:§10.3[class.virtual] / 2(强调我的):

  

如果虚拟成员函数vf在类Base和Derived中直接或间接派生的类中声明,则具有相同名称的成员函数vf,parameter-type-list,cv-qualification和ref-声明Base :: vf的限定符(或不存在),然后 Derived :: vf也是虚拟的(无论是否如此声明)并且它会覆盖Base :: vf。为方便起见我们说任何虚函数都会覆盖自己。 类对象S的虚拟成员函数C :: vf是最终覆盖,除非S是基类子对象(如果有)的最派生类声明或继承覆盖vf的另一个成员函数。在派生类中,如果基类子对象的虚拟成员函数具有多个最终覆盖,则程序格式不正确。