C++ 中的示例代码:
class A {
public:
A(int) {}
};
class B : public virtual A {
public:
B(int b) : A(b) {}
};
class C : virtual public A {
public:
C(int c) : A(c) {}
};
class D : public B, public C {
public:
D() : B(1), C(2){};
};
这是钻石问题的典型代码(解决方案)。我知道为什么使用 virtual 关键字。但是我不知道编译器处理这个问题的内部机制。现在我遇到了关于上述机制的两种不同的理论,如下所述。
当使用 virtual 关键字继承一个类时,编译器会在派生类中添加一个虚拟基指针。我检查了派生类的大小,是的,它包括附加指针的大小。但是我不知道在上面的示例中,当类 A 的成员在类 D 中引用时它指向哪里以及它是如何工作的。
对于每个构造函数,编译器为程序员提供的每个定义创建两个版本。从这个链接知道, 例如在上面的代码中。编译器会生成 2 个版本的 C 构造函数
C(int){} // Version1 C(int):A(int){} // Version2
以及两个不同版本的构造函数 B
B(int){} // Version1 B(int):A(int){} // Version2
因此,当构建 D 时,编译器将生成以下任一代码
D() : B(), C(2) {} // Version1 D() : B(1), C() {} // Version2
以确保只创建 A 的一个实例,从而避免 A 的重复副本。
请帮助我了解内部机制。