6

我偶然发现了这个代码示例:

#include <iostream>
using namespace std;

class A {
    int x;
public:
        A() { x = 1; cout << "A"; }
};
class B : virtual public A {
        int y;
public:
        B() { y = 2; cout << "B"; }
};
class C : virtual public B, virtual public A {
        int z;
public:
        C() { z = 3; cout <<"C"; }
};
class D : public A, public B, public C {
        int t;
public:
        D() { t = 4; cout << "D"; }
};
int main()
{
        D d;
        return 0;
}

这段代码打印出来ABABCD,我不知道为什么。我以为它会打印Afor D : public A,然后ABfor D : public B,然后ABCfor D : public C,然后D,但似乎A只打印了两次。这是如何运作的?

4

1 回答 1

8

基的构造顺序是(忽略虚拟基)从左到右,因为它们是在继承关系中键入的。一旦你添加了虚拟基础,它们首先以深度优先的从左到右的方式初始化(​​在任何非虚拟基础之前)。

现在这应该解释输出。

D:甲、乙、丙

A 没有虚拟基地,B 有一个虚拟 A 基地,所以这是第一个初始化的:“A”。然后 C 有一个虚拟的 B 基础,所以这是下一个正在初始化的基础。此时 A 虚拟子对象已经被初始化,所以只有 B 构造函数被评估为“AB”。至此,所有虚拟碱基都已构建完毕,非虚拟碱基也已构建,首先是 A,然后是 B,然后是 C,然后是完整的类型 D,产生“ABABCD”。虚拟子对象都已构建完毕,不再构建。

有些事情要记住。虚拟基础仅与愿意共享它的其他子对象共享(即,将其作为虚拟基础)。一个虚拟基础可以在一个完整对象中共享多少次没有限制(即 A 虚拟基础可以多次共享,包括来自不同的 B 子对象)

于 2013-06-09T12:25:36.930 回答