实现异常处理所遇到的困难主要来自于以下几个因素:第一,实现必须保证对于某一异常的合适的handler被找到。
第二,异常对象必须是多态的;这样,当实现无法通过派生类对象定位handler的时候可以考虑基类的handler。这种需要表明必须引入运行期类型检测。然而那时C++还没有任何运行期类型检测的能力。因此这种能力必须首先被实现。
作为一个附加的复杂性,实现必须能够调用所有局部对象的析构函数。这个过程被称为stack unwinding 。因为早期的C++编译器首先要把C++源文件转换为纯C,然后再把C代码编译成机器码。异常处理的实现者们不得不用C来实现运行期类型鉴别和stack unwinding。幸运的是,这些障碍已经被克服。
应用异常处理
异常处理是一种灵活并且精巧的工具。它克服了C的传统错误处理方法的缺点并且能够被用来解决一系列运行期错误。但是,异常处理也像其他语言特性一样,很容易被误用。为了能够有效的使用这一特性,理解运行期机制是如何工作的以及相关的性能花费是非常重要的。接下来的部分里将会进入异常处理的内部并且论证如何使用这一工具来建立安全的应用系统。
异常处理要素
异常处理是一种把控制权从异常发生的地点转移到一个匹配的handler的机制。异常是内建数据类型变量或者是对象。异常处理机制包括四个部分:a try block,一个或多个和try block相关的handler,throw表达式,以及异常自己。Try block包含可能抛出异常的代码。例如:
try
{
int * p = new int[1000000]; //may throw std::bad_alloc
}
一个try block后面将跟有一个或多个catch语句或者说是handlers, 每一个handler 处理不同类型的异常。例如:
try
{
int * p = new int[1000000]; //may throw std::bad_alloc
//...
}
catch(std::bad_alloc& )
{
}
catch (std::bad_cast&)
{
}
handler仅仅被在try block中的throw表达式以及函数所调用。throw表达式包括一个关键字throw以及assignment expression。例如:
try
{
throw 5; // 5 is assigned to n in the following catch statement