基类构造函数在派生类构造函数之前真的调用
我知道这个问题有明确的答案:首先调用基类构造函数,然后调用派生类构造函数。基类构造函数在派生类构造函数之前真的调用
但我不完全理解“被叫”这个词。这是否意味着构造函数的使用开始,还是构造函数的使用完成?换句话说,对于下面的代码两种可能的顺序:
BaseClass的构造开始 - > BaseClass的构造函数中完成 - > DerivedClass构造开始 - > DerivedClass构造完成。
DerivedClass构造函数启动 - > BaseClass构造函数启动 - > BaseClass构造函数完成 - > DerivedClass构造函数完成。
哪一个应该是正确的顺序?如果1是正确的,在我们初始化DerivedClass实例之前,编译器如何知道调用BaseClass构造函数?
看来情况2是正确的:“调用”应该意味着构造函数的完成。后续问题是如何解析器?我知道标准答案是“派生类的析构函数被称为第一个”。因此,这是正确的顺序为:
- DerivedClass析构函数开始
- DerivedClass析构函数完成
- BaseClass的析构函数开始
- BaseClass的析构函数完成
感谢
class BaseClass {
public:
BaseClass() {
cout << "BaseClass constructor." << endl;
}
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass() {
cout << "DerivedClass constructor." << endl;
}
};
int main() {
DerivedClass dc;
}
的CORRE CT的答案是选择1,但可以通过实际运行你已经输入了
您无法单独通过观察来验证保证。 – 2014-09-23 14:50:43
[class.base.init]/10的编码很容易地验证,重点煤矿:
在非委托构造,按照以下顺序在 初始化前进:
首先,并只对最 派生类的构造函数,虚基类被初始化[...]
然后,如它们出现在碱说明符列表 (无论MEM-初始化的量级)直接基类在 声明的顺序初始化。
然后,非静态 数据成员在他们在 类定义被宣布(再次不管 MEM-初始化的顺序)的顺序初始化。
最后,构造体的化合物语句执行。
即,派生类的构造函数被‘称为’第一,但其化合物语句(其功能体)之前,基类构造函数必须完成。我们可以看到这个命令
的一种方法是使用功能试块在派生类的构造函数:
#include <iostream>
struct Base {
Base() { throw "Base throwing\n"; }
};
struct Derived : Base{
Derived()
try : Base()
{}
catch(char const* p) {
std::cout << p;
}
};
int main() {
try { Derived d; }catch(...){}
}
的功能试块可以捕获基础和成员初始化期间发生的异常。该异常是隐式传播的:由于基本/成员不能被构造/初始化,(派生)对象不能被构造/初始化。
对于析构函数,[class.dtor]/8
执行析构函数的主体和破坏人体内分配的任何自动对象之后,对于
X
类析构函数调用析构函数X
的直接非变量非静态数据成员,破坏函数 为X
的直接基类,如果X
是最派生类的类型,其析构函数调用的析构函数10的虚拟基类。调用所有析构函数,就好像它们被引用了合格的 名称,即忽略更多派生类中的任何可能的虚拟覆盖析构函数。按照完成构造函数的相反顺序销毁基地和成员。
如果析构函数是虚拟的,编译器(有时)无法知道在销毁站点/转换单元中必须调用哪些析构函数(派生类型最多的类型)。因此,析构函数本身必须调用基础和成员的销毁(至少对于通过动态分派调用的虚拟析构函数)。
感谢您的意见@dyp。你的意思是对于析构函数来说,构造函数的顺序应该是相似的吗? DerivedClass析构函数启动 - > BaseClass析构函数启动 - > BaseClass析构函数完成 - > DerivedClass析构函数完成。 – cgao 2014-09-23 15:36:05
不,正如引用所述:“在执行析构函数的主体[...]之后,类'X'的析构函数调用了'X'的直接基类的析构函数[...] ]“。也就是,顺序是:'〜Derived()'starts - >'〜Derived()'的主体完成 - >'〜Base()'starts - >'〜Base()'的主体完成。对于* *体的执行,构造函数和析构函数之间的顺序是相反的。 – dyp 2014-09-23 15:45:18
为什么不运行该程序并找出答案? – 2014-09-23 14:13:23
试试看,一个重要的座右铭;)。 – 2014-09-23 14:13:54
如果2是正确的,那么在派生类构造函数中的基准类构造函数是否会被“注入”?编译器如何做出该决定? – 2014-09-23 14:14:20