c++ - 虚拟继承如何解决 "diamond"(多重继承)的歧义?

标签 c++ inheritance multiple-inheritance virtual-inheritance diamond-problem

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 

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

A   A  
|   |
B   C  
 \ /  
  D 

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

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

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

Wikipedia has another good rundown and example here

关于c++ - 虚拟继承如何解决 "diamond"(多重继承)的歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2659116/

相关文章:

c++ - 迭代器解引用问题

c++ - 重载赋值运算符的问题

javascript - "Extend"JS 数组就像传统的 OO 语言一样吗?

c++ - 构造函数的继承错误调用

c# - 为什么接口(interface)支持多重继承而类在 C# 中不支持

c++ - 为有条件编译的产品实现工厂模式

c++ - 如何在 Windows 上停止 boost::ioservice

python - 如何在继承类中执行常见的后初始化任务?

oop - 深度继承层次结构的替代方案?

c++ - 将多重继承的对象转换到 void* 或从 void* 转换