异常处理中的构造和析构
本人节选自《21天学通C++》一书
当在程序中找到一个匹配的catch异常处理后,如果catch()语句的异常类型声明是一个值参数,则其初始化方式是复制被抛弃的异常对象;如果catch()语句的异常类型声明是一个引用,则其初始化方式是使该引用指向异常对象。
【范例20-4】使用带析构的类的异常处理。该范例包含类及其构造函数与析构函数,其进行异常处理时析构函数的调用会有所不同,代码如代码清单20-4所示。
代码清单20-4
1 #include<iostream.h>
2 class expt //定义类expt
3 {
4 public: //定义公有成员
5 expt() //定义构造函数
6 {
7 cout<<"structor of expt"<<endl;
8 }
9 ~ expt() //定义析构函数
10 {
11 cout<<"destructor of expt"<<endl;
12 }
13 };
14 class demo //定义类demo
15 {
16 public:
17 demo() //定义构造函数
18 {
19 cout<<"structor of demo"<<endl;
20 }
21 ~demo() //定义析构函数
22 {
23 cout<<"destructor of demo"<<endl;
24 }
25 };
26 void fuc1() //定义函数
27 {
28 int s=0;
29 demo d; //声明demo类的对象
30 throw s; //抛出异常
31 }
32 void fuc2()
33 {
34 expt e; //声明expt类的对象
35 fuc1(); //调用函数fuc1
36 }
37 void main()
38 {
39 try //定义异常
40 {
41 fuc2(); //调用函数
42 }
43 catch(int) //定义异常处理
44 {
45 cout<<"catch int exception"<<endl;
46 }
47 cout<<"continue main()"<<endl;
48 }
【运行结果】在Visual C++中新建一个【C++ Source File】文件,输入上述的代码,编译无误后运行。
【范例解析】上述代码中定义了两个类expt和demo,在函数fuc2()中创建了expt的对象e,在函数fuc1()中创建了demo的对象d,并抛出异常。在主函数main()中,使用try/catch语句捕获并处理异常。从运行结果可以看出,在抛弃异常前,创建了两个对象e和d,在抛弃异常后,这两个对象被按与创建的相反顺序调用析构函数销毁。
注意:当catch()语句的异常类型参数被初始化后,便开始了栈的展开过程,包括从对应的try语句块开始到异常被抛弃之间对构造的所有自动对象进行析构。析构的顺序与构造的顺序相反。然后程序从最后一个catch处理之后开始恢复。