异常处理中的析构函数
- C++异常处理的真正能力不仅在于它能处理各种不同类型的异常,还在于它具有异常处理前为构造的所有局部对象自动调用析构函数的能力。
- 如果try块(或try块调用的函数)中定义了类对象,在建立该对象时要调用构造函数。如果在执行try块(或try块调用的函数)的过程中发生了异常,此时流程立即离开try块。那么此时流程就可能离开该对象的作用域而转到其他函数,因此应当做好结束对象前的清理工作。
- C++的异常处理机制会在throw抛出异常信息被catch捕获时,对有关的局部对象进行析构(调用相应类对象的析构函数),析构的顺序和构造的顺序相反,然后执行与异常信息匹配的catch块中的语句
- 如下面的代码实例:
#include <iostream>
using namespace std;
class Student{
private:
string name;
int sno;
public:
Student(string name1,int sno1)
{
name=name1;
sno=sno1;
}
~Student()
{
cout<<"Destruct Student:"<<sno<<endl;
}
void checkSno()
{
if(sno==0)
{
throw sno;
}
else
{
cout<<name<<":"<<sno<<endl;
}
}
};
int main()
{
try
{
Student a("pink",1);
a.checkSno();
Student b("floyd",0);
b.checkSno();
}
catch(int)
{
cout<<"error:sno=0!"<<endl;
}
return 0;
}
构造函数中的异常处理
- 如果在初始化类对象时构造函数发生了异常,则该类对象可能只是部分被构造:有些成员初始化,有些成员还没有初始化。如果系统没有完整的创建一个类对象,则系统不会调用析构函数来释放它,这就使得析构函数发生异常前的成员有时不会被释放。
- 下面是由前面的例子改变后的实例:
- 结果当然是对象没有被析构。
- 处理方法是:在构造函数发生异常时,需要保证已创建的类对象成员能够被释放,然后才抛出异常。
#include <iostream>
using namespace std;
class Student{
private:
string name;
int sno;
public:
Student(string name1,int sno1)
{
cout<<"Construct Stduent"<<endl;
if(sno1==0)
{
throw sno1;
}
name=name1;
sno=sno1;
}
~Student()
{
cout<<"Destruct Student:"<<sno<<endl;
}
};
int main()
{
try
{
Student a("floyd",0);
}
catch(int)
{
cout<<"error:sno=0!"<<endl;
}
return 0;
}