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

2024-05-19

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,但它有两条可以遵循的路径,但不能自行决定。

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


你要:(可通过虚拟继承实现)

  A  
 / \  
B   C  
 \ /  
  D 

And not:(没有虚拟继承会发生什么)

A   A  
|   |
B   C  
 \ /  
  D 

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

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

So B::A and C::A是相同的,因此不会有任何含糊的调用D。如果您不使用虚拟继承,您将看到上面的第二张图。然后,对 A 成员的任何调用都会变得不明确,您需要指定要采用的路径。

维基百科在这里有另一个很好的概述和例子 http://en.wikipedia.org/wiki/Virtual_inheritance

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

虚拟继承如何解决“钻石”(多重继承)的歧义? 的相关文章

随机推荐