在异常处理中处理析构函数
一个例子:
输出结果:
#include<iostream> #include<string> using namespace std; class Student { public: Student(int n,string nam) { num=n; name=nam; cout<<"constructor-->"<<num<<endl; } ~Student() { cout<<"destructor-->"<<num<<endl; } void get_data(); private: int num; string name; }; void Student::get_data() { if(num==0)throw num; //当num=0的时候,将int型变量num抛出 else cout<<num<<" "<<name<<endl;//当num≠0的时候,输出num和name cout<<"in get_data()"<<endl; //输出信息,表示目前在get_data中 } void fun() { Student stud1(1,"Tan"); stud1.get_data(); cout<<"\n============分割线呼啸而过======================\n"<<endl; Student stud2(0,"Li"); stud2.get_data(); } int main() { cout<<"main begin"<<endl; cout<<"call fun()"<<endl; try { fun(); } catch(int n) { cout<<"num="<<n<<",error!"<<endl; } cout<<"main end"<<endl; return 0; }
输出结果:
/* main begin call fun() constructor-->1 1 Tan in get_data() ============分割线呼啸而过====================== constructor-->0 destructor-->0 destructor-->1 num=0,error! main end */
分析:函数fun中,当执行到stud2.get_data()的时候,get_data函数抛出异常,因为get_data函数中没够catch结果,所以无法捕捉异常,只能像上级传递,返回到了fun函数中。在fun中也没有catch结构,所以就又返回到了main函数中。因为stud1和stud2实在fun函数中定义的,所以当异常从catch返回到main函数的时候,这两个对象的生命周期已经结束,所以按照“先构造的对象后析构”的原则进行析构,所以输出destructor-->0和destructor->1。然后等到了main函数中,发现有与之匹配的catch函数,所以执行执行异常操作,然后继续执行异常操作之后的语句。
从这个例子还可以看出,我们抛出异常的位置一般位于函数体的首部,在函数体中首先进行检验,发现有异常就立即抛出,因为它继续执行函数体中的接下来的语句是没有意义的。