一个例子:
输出结果:
#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函数,所以执行执行异常操作,然后继续执行异常操作之后的语句。
从这个例子还可以看出,我们抛出异常的位置一般位于函数体的首部,在函数体中首先进行检验,发现有异常就立即抛出,因为它继续执行函数体中的接下来的语句是没有意义的。