2

我有这个 C++ 代码:

class BaseClass {
    int id;
public:
    BaseClass() { printf("BaseClass()\n"); }
    virtual ~BaseClass() { printf("~BaseClass()\n"); }
};

class Class1 : public BaseClass
{
    int id;
public:
    Class1() { printf("Class1()\n"); }
    ~Class1() { printf("~Class1()\n"); }
};

class Class2 : public Class1
{
    BaseClass id;
public:
    Class2() { printf("Class2()\n"); }
    ~Class2() { printf("~Class2()\n"); }
};

class Class3 : virtual public BaseClass
{
    int id;
public:
    Class3() { printf("Class3()\n"); }
    ~Class3() { printf("~Class3()\n"); }
};

class Class4 : public Class3, virtual public Class1
{
    Class3 id;
public:
    Class4() { printf("Class4()\n"); }
    ~Class4() { printf("~Class4()\n"); }
};

int main(int argc, char* argv[])
{
    BaseClass *p = new Class2;
    Class2 *p1 = new Class2;
    Class3 *p2 = new Class3;
    delete p;
    delete p1;
    delete p2;
    return 0;
}

这是输出:

BaseClass()
Class1()
BaseClass()
Class2()
BaseClass()
Class1()
BaseClass()
Class2()
BaseClass()
Class3()
~Class2()
~BaseClass()
~Class1()
~BaseClass()
~Class2()
~BaseClass()
~Class1()
~BaseClass()
~Class3()
~BaseClass()

我不明白为什么。我希望输出如下:

BaseClass()
Class1()
Class2()
BaseClass()
Class1()
Class2()
...

等等

为什么创建后不Class2()打印Class1(),例如,p1?这与虚拟继承有关吗?

4

2 回答 2

3

为什么在创建例如 p1 时在 Class1() 之后不打印 Class2()?

因为Class2有一个类型为 的非静态成员对象BaseClass,所以它的 ctor 会在 的 ctor 之前被调用Class2

根据初始化顺序

初始化顺序

1)如果构造函数是针对最派生类的,则虚基类按照出现的顺序进行初始化,深度优先从左到右遍历基类声明(从左到右指出现在基本说明符列表中)

2) 然后,直接基类按照从左到右的顺序初始化,因为它们出现在此类的基说明符列表中

3) 然后,按照类定义中的声明顺序初始化非静态数据成员。

4) 最后执行构造函数的主体

对于,将首先调用new Class2;直接基类Class1及其基类。然后将调用具有类型BaseClass的非静态数据成员。最后将调用ctor of 的主体。所以你会得到idBaseClassClass2

BaseClass()
Class1()
BaseClass()
Class2()
于 2016-05-07T13:57:51.730 回答
2

让我们一步一步地构造第一个对象:

new Class2;

这是您正在构建的第一个对象,我们称之为p

BaseClass()

pBaseClass

Class1()

p,的Class1子类BaseClass被构造。

BaseClass()

这是被构造的id成员。Class2

Class2()

现在,最后Class2p它本身。

因此,尽管您Class2()不相信,但在Class1(). 除了您忘记了它Class2还有一个id成员,那就是 a BaseClass,并且还必须在Class2::Class2()调用构造函数之前构造它。您认为您看到的是正在构造第二个newed 对象,但真正构造的是成员对象。BaseClassBaseClass

PS这是C++。在C++我们使用std::cout而不是printf()。printf()就是这样……上个世纪。

于 2016-05-07T13:50:56.207 回答