C++ 虚拟继承奇怪的行为

C++ Virtual Inheritance weird behavior

struct A {
public:
    A() {
        std::cout << "A" << std:: endl;
    }
    void foo() { std::cout << "foo is called from A"; }
};

struct B : virtual A {  };
struct C : virtual  A {  };
struct D : B, C { D() { std::cout << "D" << std::endl; } };

struct E : D { };
struct F : D {};
struct G : E, F {}; 


int main()
{
    G g;
    g.foo();
}

输出代码为:

这毫无意义。对象 D 被构造了两次。为什么编译器不抱怨 foo 不明确? G 如何知道 foo 上只有一个定义? (在这种情况下,D 被制作了两次,我没有使用虚拟继承,但不知何故它知道。) 老实说,我认为 E 和 F 实际上也应该从 D 继承,以避免 foo 的模糊定义。 任何人都可以提供一个很好的解释吗? 在 VS 2017 中编译 Windows。 你可以把这条继承线想象成一个双菱形问题

Object D is constructed twice.

这是因为该对象有两个 D 碱基。一个通过 E,另一个通过 F

Why doesn't the compiler complain that foo is ambiguous?

因为只有一个A基地。这是因为它是一个虚拟基地。对于每个具体实例,总是只有一个其类型的虚拟基础子对象。

这是继承的粗略 ASCII 艺术:

non-virtual  |   virtual
             |   A
 ____________|__/
/   /  /  /  |
B  C  B  C   |
 \/    \/    |
  D     D    |
   \   /     |
    E  F     |       bases
_____\/______________________
      G              concrete

How does the compiler know that multiple D should contain the same base A

因为它知道所有这些 A 碱基都是虚拟的。

This makes no sense.

为什么?这正是虚拟继承的目的。 G 中只有一个 A 子对象。说明符在我们沿着层次结构向下移动时保持不变,因此即使 G 有两个 D,它们都共享一个 A.