15.3

15.3 异常

调用abort()

返回错误码

异常机制

try {}
catch (异常类型) {}
throw 异常类型的变量/对象;
捕获所有异常:
catch (...) {}

将对象作为异常类型

异常规范和C++11

栈解退

try块中的函数调用了引发异常的函数, 程序将从引发异常的函数跳转的try块和处理程序的函数, 涉及到栈解退。
栈解退将会释放throw到达try块前栈中所有的函数和对象(调用析构函数)。

其他异常特性

throw 引发的异常是临时拷贝。
捕获父类的引用, 可以将子类的也一起捕获, 所以父类应该放在最后。

exception类

异常、类和继承

异常何时会迷失方向

未捕获异常
terminate()-->abort()
set_terminate()修改terminate调用的函数
意外异常
unexpected()-->terminated()-->abort()
set_unexpected()修改unexpected()调用的函数
意外异常较为复杂。。如果unexpected()调用的函数引发了一个新的异常... ... P640

有关异常的注意事项

缺点:
使用异常增加程序代码, 降低程序运行速度, 异常规范不适用于模板, 异常和动态内存分配并不总能协同工作。
动态内存分配和异常
栈解退时, 栈中的自动变量会被释放, 但是动态分配的内存将不会被释放。--内存泄漏。
可以在引发异常的函数中捕获该异常, 然后再catch块中包含一些清理代码, 然后重新引发该异常:
double *ar = new double[n];
try
{
if (oh_no)
throw exception();
}
catch (exception &ex)
{
delete [] arr;
throw;
}
但是, 这件共增加疏忽和产生其他错误的机会。另一种解决办法:第十六章将讨论只能指针模板。