Second Edition
17.2 抛出异常
如果程序发生异常情况,而在当前的上下文环境中获取不到异常处理的足够信息,我们可以创建一个包含出错信息的对象并将该对象抛出当前上下文环境,将错误信息发送到更大的上下文环境中。这称为异常抛出。例如:
throw myerror("something bad happened");
myerror是一个普通类,它以字符变量作为其参数。当进行异常抛出时我们可使用任意类型变量作为其参数(包括内部类型变量),但更为常用的办法是创建一个新类用于异常抛出。关键字throw的引入引起了一系列重要的相关事件发生。首先是throw调用构造函数创建一个原执行程序中并不存在的对象。其次,实际上这个对象正是throw函数的返回值,即使这个对象的类型不是函数设计的正常返回类型。对于交替返回机制,如果类推太多有可能会陷入困境,但仍可看作是异常处理的一种简单方法,可通过抛出一个异常来退出普通作用域并返回一个值。因为异常抛出同常规函数调用的返回地点完全不同,所以返回值同普通函数调用具有很小的相似性(异常处理器地点与异常抛出地点可能相差很远)。只有在异常时刻成功创建的对象才被清除掉。(常规函数调用则不同,它使作用域内的所有对象均被清除。)当然,异常情况产生的对象本身在适当的地点也被清除。我们可根据要求抛出许多不同类型的对象。一般情况下,对于每种不同的错误可设定抛出不同类型的对象。采用这样的方法是为了存储对象中的信息和对象的类型,所以别人可以在更大的上下文环境中考虑如何处理我们的异常。
更多关于异常处理的知识可以参考 C++编程思想异常处理 和 未捕获异常处理。
17.3 异常捕获
如果一个函数抛出一个异常,它必须假定该异常能被捕获和处理。正如前文所提到的,允许对一个问题集中在一处解决,然后处理在别处的差错,这也正是C++语言异常处理的一个优点。
17.3.1 try块
如果在函数内抛出一个异常(或在函数调用时抛出一个异常),将在异常抛出时退出函数。如果不想在异常抛出时退出函数,可在函数内创建一个特殊块用于解决实际程序中的问题(和潜在产生的差错)。由于可通过它测试各种函数的调用,所以被称为测试块。测试块为普通作用域,由关键字try引导:
try {
// code that may generate exceptions
}
当我们运行这个例子时会惊奇地发现—一些C++编译器调用longjmp()函数清除堆栈中的对象。这是兼容性差的问题。
有关更多信息,请参阅 Crash异常捕获与处理 和 Android捕获全局异常处理。