c++ 如何虚拟继承解决“钻石”(多重继承)歧义?

class A                     { public: void eat(){ cout<<"A";} }; 
class B: virtual public A   { public: void eat(){ cout<<"B";} }; 
class C: virtual public A   { public: void eat(){ cout<<"C";} }; 
class D: public         B,C { public: void eat(){ cout<<"D";} }; 

int main(){ 
    A *a = new D(); 
    a->eat(); 
} 

我理解钻石问题,上面的代码没有那个问题。

虚拟继承究竟如何解决这个问题?

我明白:
当我说A * a = new D();,编译器想知道类型D的对象是否可以分配给类型A的指针,但它有两个路径,它可以跟随,但不能自己决定。

那么,虚拟继承如何解决问题(帮助编译器作出决定)?

最佳答案
你想要:(用虚拟继承可实现)

  D  
 / \  
B   C  
 \ /  
  A 

而不是:(没有虚拟继承会发生什么)

  D  
 / \  
B   C  
|   |  
A   A 

虚拟继承意味着只有一个基类的实例A类不是2。

你的类型D有2个vtable指针(你可以在第一个图中看到它们),一个用于B,一个用于C,它们虚拟地继承A.D的对象大小增加,因为它现在存储2个指针;然而现在只有一个A.

所以B :: A和C :: A是相同的,所以可以没有来自D的模糊调用。如果你不使用虚拟继承,你有上面的第二个图。然后,对A成员的任何调用都变得模糊,您需要指定要采用的路径。

Wikipedia has another good rundown and example here

转载注明原文:c++ 如何虚拟继承解决“钻石”(多重继承)歧义? - 代码日志