为什么单个虚拟继承不足以解决可怕的钻石问题?

时间:2011-07-08 06:03:59

标签: c++ language-lawyer virtual-inheritance diamond-problem

struct B { int i; };
struct D1 : virtual B {};
struct D2 : B {};  // <-- not virtual
struct DD : D1, D2 {};

上面编码后,编译器仍然要求D2virtual

DD d;
d.i = 0; // error: request for member `i' is ambiguous

我不明白的是,一旦你提示编译器B virtualDDD1),那么为什么它仍然i 1}}含糊不清?

(如果我的记忆服务正确,那么旧的VC ++(2006年)就足以用单virtual个继承来证明这一点

3 个答案:

答案 0 :(得分:7)

B对于DD不是虚拟的 - 它相对于D1是虚拟的。在创建D2时,它包含B的完整副本。所以现在DD有两个B实现:一个作为D2的一部分,一个作为结尾(由D1指向)。有i的两份副本,使用它确实含糊不清。

如果D2也使用虚拟继承,而不是包含B的副本,它将包含指向D1也指向的B实例的指针,而DD只包含一个B实例。

我将尝试说明内存布局,希望这是正确的......:

你的情况,有一个虚拟继承和一个非虚拟 -

|    D1    |   D2 + B |    B    |
+--+-------+----------+---------+
 |   vptr to B           ^
 +-----------------------|

让D1和D2都虚拟地继承 -

|   D1   |   D2   |   B   |
+--+-----+---+----+-------+
 |         |         ^
 +---------+---------|

答案 1 :(得分:2)

您必须阅读Diamond problem。在方法标题下,对于CPP,您的案例被明确提及,您的观察与那里解释的一致。

答案 2 :(得分:2)

该标准要求d.i在这种情况下必须含糊不清。 ISO / IEC 14882:2003第10.1.6节涵盖了具有给定类型的虚拟和非虚拟基类的类。