1 析构函数中是否可以抛出异常
首先我们看一个常见的问题,析构函数中是否可以抛出异常。答案是C++标准指明析构函数不能、也不应该抛出异常!
C++异常处理模型是为C++语言量身设计的,更进一步的说,它实际上也是为C++语言中面向对象而服务的。C++异常处理模型最大的特点和优势就是对C++中的面向对象提供了最强大的无缝支持。那么如果对象在运行期间出现了异常,C++异常处理模型有责任清除那些由于出现异常所导致的已经失效了的对象(也即对象超出了它原来的作用域),并释放对象原来所分配的资源, 这就是调用这些对象的析构函数来完成释放资源的任务,所以从这个意义上说,析构函数已经变成了异常处理的一部分。
下面我们来看看析构函数中不能抛出异常的两个理由:
1)如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成诸如资源泄漏的问题。
2)通常异常发生时,c++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃的问题。
那么当无法保证在析构函数中不发生异常时, 该怎么办?
其实还是有很好办法来解决的。那就是把异常完全封装在析构函数内部,决不让异常抛出函数之外。这是一种非常简单,也非常有效的方法。
//析构函数
~Class()
{
try{
}
catch(){ //这里可以什么都不做,只是保证catch块的程序抛出的异常不会被扔出析构函数之外。
}
}
2 程序抛出异常后会怎样
下面我们通过一个程序来观察当程序中抛出异常了是否会调用析构函数,异常抛出中throw()后面的语句是否还会执行。程序如下,我们创建一个类,然后构造一个类对象,当抛出异常我们看程序是否会进入析构函数以及throw()抛出异常后面的程序:
#include<iostream>
using namespace std;
class setTry{
public:
setTry(){ //构造函数
cout << "start!" << endl; // 1
}
~setTry(){ //析构函数
cout << "end!" << endl; // 4
}
void dosomething(){
cout << "do something!" << endl; //类方法
}
};
int main(void)
{
setTry newOne;
try{
throw("error!"); //直接抛出异常
newOne.dosomething();
}
catch (char* one){ //接收char*类异常
cout << one << endl; // 2
}
catch (...){ //接收其他类型异常
cout << "..." << endl;
}
cout << "return 0!"<<endl; // 3
return 0;
}
上面程序运行结就是按标注的1、2、3、4步骤输出的,结果如下图所示:
从运行结果就可以看出,抛出异常try内部的throw()后面程序不会再执行,而try外部后面的程序会继续执行。另外,析构函数在生存期结束也会被调用。
参考文献:
http://blog.csdn.net/u012398613/article/details/17469581