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

在上面编码之后,编译器仍然D2要求virtual

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

我不明白的是,一旦您提示了与(via ) 相关的编译B器,那么为什么它仍然是模棱两可的?virtualDDD1i

(如果我没记错的话,较旧的 VC++(2006 年)足以通过单virtual继承来解决这个问题)

4

3 回答 3

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   |
+--+-----+---+----+-------+
 |         |         ^
 +---------+---------|
于 2011-07-08T06:21:34.320 回答
2

您必须阅读钻石问题。在“方法”标题下,对于 CPP,您的案例被明确提及,您的观察结果与那里解释的一致。

于 2011-07-08T06:11:19.683 回答
2

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

于 2011-07-08T06:44:12.550 回答