C虚拟方法的虚拟继承

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(),则会发生错误).那有什么区别?为什么我们在虚拟地继承我们的类时会出现错误,如果我们直接执行它就没有错误?

最佳答案
使A成为B和C的虚基类可确保D只包含一个A子对象[1].为此,B和C都为foo [2]提供了最终的覆盖,并且两者都由D [2]继承,因此D有两个foo的最终覆盖,使程序格式错误[2].

当A不是B和C的虚基类时,D将包含两个不同的A子对象[1].每个子对象都有自己的foo继承的最终覆盖[2].

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

A base class specifier that does not contain the keyword virtual, specifies a non-virtual base class. A base class specifier that contains the keyword virtual, specifies a virtual base class. For each distinct occurrence
of a non-virtual base class in the class lattice of the most derived class, the most derived object shall contain a corresponding distinct base class subobject of that type. For each distinct base class that is specified virtual, the most derived object shall contain a single base class subobject of that type.

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

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf. For convenience we say that any virtual function overrides itself. A virtual member function C::vf of a class object S is a final overrider unless the most derived class of which S is a base class subobject (if any) declares or inherits another member function that overrides vf. In a derived class, if a virtual member function of a base class subobject has more than one final overrider the program is ill-formed.

转载注明原文:C虚拟方法的虚拟继承 - 代码日志