解释此 C++ 代码中 constructor/destructor 调用的顺序
Explain order of constructor/destructor calls in this C++ code
我有这个 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()
...
等等
为什么在创建时Class1()
之后不打印Class2()
,例如p1
?
这跟虚拟继承有关系吗?
让我们逐步构建第一个对象:
new Class2;
这是您正在构建的第一个对象,我们将其命名为 p
。
BaseClass()
p
的 BaseClass
.
Class1()
p
的Class1
,构建了BaseClass
的子类。
BaseClass()
这是正在构建的 Class2
的 id
成员。
Class2()
现在,终于 Class2
,p
本身。
因此,尽管您不这么认为,Class2()
还是打印在 Class1()
之后。除了你忘记了 Class2
也有一个 id
成员,那是一个 BaseClass
,而且它也必须在调用 Class2::Class2()
构造函数之前构造。您认为您正在构建第二个 new
ed 对象的 BaseClass
,但真正构建的是 BaseClass
成员对象。
P.S。这是C++
。在 C++
中,我们使用 std::cout
而不是 printf
()。 printf()
上世纪如此。
Why isn't Class2() printed after Class1() when creating, for example, p1?
因为Class2
有一个类型为BaseClass
的非静态成员对象,它的ctor会在Class2
的ctor之前被调用。
Initialization order
1) If the constructor is for the most-derived class, virtual base
classes are initialized in the order in which they appear in
depth-first left-to-right traversal of the base class declarations
(left-to-right refers to the appearance in base-specifier lists)
2) Then, direct base classes are initialized in left-to-right order as
they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of
declaration in the class definition.
4) Finally, the body of the constructor is executed
对于new Class2;
,直接基classClass1
及其基classBaseClass
将首先被调用。然后将调用类型为 BaseClass
的非静态数据成员 id
。最后会调用 Class2
的 ctor 主体。所以你会得到
BaseClass()
Class1()
BaseClass()
Class2()
我有这个 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()
...
等等
为什么在创建时Class1()
之后不打印Class2()
,例如p1
?
这跟虚拟继承有关系吗?
让我们逐步构建第一个对象:
new Class2;
这是您正在构建的第一个对象,我们将其命名为 p
。
BaseClass()
p
的 BaseClass
.
Class1()
p
的Class1
,构建了BaseClass
的子类。
BaseClass()
这是正在构建的 Class2
的 id
成员。
Class2()
现在,终于 Class2
,p
本身。
因此,尽管您不这么认为,Class2()
还是打印在 Class1()
之后。除了你忘记了 Class2
也有一个 id
成员,那是一个 BaseClass
,而且它也必须在调用 Class2::Class2()
构造函数之前构造。您认为您正在构建第二个 new
ed 对象的 BaseClass
,但真正构建的是 BaseClass
成员对象。
P.S。这是C++
。在 C++
中,我们使用 std::cout
而不是 printf
()。 printf()
上世纪如此。
Why isn't Class2() printed after Class1() when creating, for example, p1?
因为Class2
有一个类型为BaseClass
的非静态成员对象,它的ctor会在Class2
的ctor之前被调用。
Initialization order
1) If the constructor is for the most-derived class, virtual base classes are initialized in the order in which they appear in depth-first left-to-right traversal of the base class declarations (left-to-right refers to the appearance in base-specifier lists)
2) Then, direct base classes are initialized in left-to-right order as they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of declaration in the class definition.
4) Finally, the body of the constructor is executed
对于new Class2;
,直接基classClass1
及其基classBaseClass
将首先被调用。然后将调用类型为 BaseClass
的非静态数据成员 id
。最后会调用 Class2
的 ctor 主体。所以你会得到
BaseClass()
Class1()
BaseClass()
Class2()