这个问题在这里已有答案:
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中编译。您可以将这一继承线想象为双钻石问题。
这毫无意义。
为什么?这正是虚拟继承的用途。在A
中只有一个G
子对象。当我们沿着等级划分时,说明者坚持,所以即使G
有两个D
,他们都共享一个A
。
对象D构造两次。
这是因为该物体有两个D
基地。一个通过E
,另一个通过F
。
为什么编译器不抱怨foo是不明确的?
因为只有一个A
基地。这是因为它是一个虚拟基础。对于每个具体实例,始终只有一个类型的虚拟基础子对象。
这是一个粗略的ASCII艺术继承:
non-virtual | virtual
| A
____________|__/
/ / / / |
B C B C |
\/ \/ |
D D |
\ / |
E F | bases
_____\/______________________
G concrete
编译器如何知道多个D应该包含相同的基数A.
因为它知道所有这些A碱基都是虚拟的。