如果类中没有写析构函数,则系统生成一个内联的,不会抛出异常的的析构函数,如下:
class B {
public:
B(){}
inline ~B()noexcept { //inline意味着这个函数会展开,这会造成的问题是代码会变大
try {
//一些清理工作
}
catch (...) {
std::terminate();
}
}
};
当B的析构函数执行完毕,还会调用B的成员函数的析构。比如他有个string类型的数据成员,则执行完 ~B()之后会执行~string()。
在执行完成员的析构函数之后,会调用基类的析构函数。
析构函数抛出异常是一个坑,例如下面的代码,我们让B类析构函数抛出异常:
class A {
public:
~A() {
cout << "A" << endl;
}
};
class B :public A {
public:
~B() {
throw string("error");
}
};
void test() {
try {
B b;
}
catch (...) {
cout << "catch U evil" << endl;
}
}
int main() {
test();
return 0;
}
对于析构函数,如果我们不指出来析构函数的声明类型,则析构函数默认的是 noexcept类型的。
class B :public A {
public:
~B() noexcept {
throw string("error");
}
};
因此析构函数抛出异常会导致程序崩溃。
如果你就是想让析构函数抛出异常,可以这样设置吗?
~B() noexcept(false) {
throw string("error");
}
运行一下修改后的代码,似乎没有问题
class A {
public:
~A() {
cout << "hi A" << endl;
}
};
class B :public A {
public:
~B() {
cout << "hi B" << endl;
}
};
class C :public B {
public:
~C() noexcept(false) {
throw string("error");
}
};
void test() {
try {
C c;
}
catch (...) {
cout << "catch U evil" << endl;
}
}
答案是——不可以!!!!!
假如B类中也抛出一个异常
class A {
public:
~A() {
cout << "hi A" << endl;
}
};
class B :public A {
public:
~B() noexcept(false) {
cout << "hi B" << endl;
throw string("error");
}
};
class C :public B {
public:
~C() noexcept(false) {
throw string("error");
}
};
void test() {
try {
C c;
}
catch (...) {
cout << "catch U evil" << endl;
}
}
执行一次try,C和B两个类都抛出了异常,C++在一次try时只能处理一个异常。
如果小杠精说:我保证写的基类和派生类中只有一个异常,总可以了吧?答案依然是——不可以
class A {
public:
~A() {
cout << "hi A" << endl;
}
};
class B :public A {
public:
~B() {
cout << "hi B" << endl;
}
};
class C :public B {
public:
~C() noexcept(false) {
throw string("error");
}
};
void test() {
try {
C b;
C c;
}
catch (...) {
cout << "catch U evil" << endl;
}
}
还是因为只能处理一个异常。
这就是为什么析构函数默认是noexcept的原因