c++异常处理的真正能力,不仅在于他能够处理各种不同类型的异常,还在于它具有为异常抛掷前构造的所有局部对象自动调用析构函数的能力。
在程序中,找到一个匹配的catch异常处理后,如果catch子句的异常类型声明是一个值参数,则其初始化方式是复制被抛掷的异常对象。如果catch子句的异常类型声明是一个引用,则其初始化方式是使该引用指向异常对象。
当catch子句的异常类型声明参数被初始化后,栈的展开过程便开始了。这包括将从对应的try块开始到异常被抛掷处之间构造(且尚未析构)的所有自动对象进行析构。析构的顺序与构造的顺序相反。然后程序从最后一个catch处理之后开始恢复执行。
例子:
#include<iostream>
using namespace std;
void MyFunc(void);
class Expt {
public:
Expt(){}
~Expt(){}
const char *ShowReason() const
{ return "Expt类异常"; }
};
class Demo
{
public:
Demo();
~Demo();
};
Demo::Demo() { cout << "构造Demo" << endl; }
Demo::~Demo() { cout << "析构Demo" << endl; }
void MyFunc() {
Demo D;
cout << "在MyFunc()中抛掷Ecpt类异常." << endl;
throw Expt();
}
int main()
{
cout << "在main函数中." << endl;
try{
cout << "在try块中,调用M有Func()." << endl;
MyFunc();
} catch (Expt E) {
cout << "在catch异常处理程序中。" << endl;
cout << "捕获到Expt类型异常:";
cout << E.ShowReason() << endl;
}
catch (char *str)
{ cout << "捕获到其他的异常:" << str << endl; }
cout << "回到main函数。从这里恢复执行。" << endl;
getchar(); getchar();
return 0;
}
其实,也可以不说明这些参量E(或者str)。在很多情况下只要通知处理程序有某个特定类型的异常已经产生就足够了。但是在需要访问异常对象时就要说明参量。否则将无法访问catch处理程序子句中的那个对象。例如
catch(Expt)
{ //在这里不能访问Expt异常对象}
4.标准程序库异常处理