栈展开
析构函数应该从不抛出异常,栈为某个异常进行栈展开的时候,析构函数如果抛出自己的末尾处理的另一个异常,会导致调用标准库terminal函数,该函数将调用abort函数,强退。
析构函数经常会抛出异常,类似的,初始化数组或容器类型的元素时,也可能发生异常,如果一场对象找不到匹配的catch,则调用terminal
捕获异常
catch子句中的一场说明符看起来像只包含一个形参的形参标,异常说明符是在后跟一个形参明的类型名
在查找匹配的catch期间,找到的catch不必与异常最匹配那个,相反,将选中第一个找到的可以处理异常的catch,所以,在catch子句列表中,最特殊的catch必须最先出现
出了几种有区别,宜昌的类型与catch说明符的类型必须完全匹配:
1、允许从非const到const的转换,也就是非const对象的throw,可以指定接受const引用的catch匹配
2、允许从派生类型到基类类型的转换
3、将数组转换为指向数组类型的指针,将函数转换为指向函数类型的适当指针
重新抛出
有可能单个catch不能完全处理一个异常,该异常必须有函数调用链中更上层的函数来处理。catch可以通过更新抛出,重新抛出时候面部根类型或表达式的一个throw,只能出现在catch或者从catch调用的函数
catch( my_error &eobj )
{
eobj.status=sever_err; //modefies the exception object
throw;
}
catch( other_error eobj )
{
eobj.status=bad_err; //modefies local copy only
throw;
}
一般而言,catch可以改变它的形参,再改变形参后,如果catch重新跑出异常,那么,只有当异常说明符为饮用的时候才会改变
捕获所有异常的catch子句形式为(...)
catch(...)
{
//place our code here
}
catch(...)经常与重新抛出表达式结合使用,catch完成可做的所有局部工作,然后重新抛出异常
void manip()
{
try
{
//actions that cause an exception to be throw
}
catch(...)
{
//work to partially handle the exception
throw;
}
}
如果catch(...)与其它catch子句结合使用,它必须是最后一个,否则,任何跟在他后面的catch自居都不能匹配
为了处理来自析构函数初始化的异常,必须将构造函数编写为函数测试块
template<typename T>
{
Handle<T>::Handle<T *p>try:ptr(p),use(new size_t(1)){}
}
catch(const bad_alloc &e)
{
handle(e_out_of_memory(e));
}
关键字try出现在成员初始化列表之前,并且测试块的复合语句包围了构造函数的函数体,catch子句既可以处理从成员初始化列表中抛出的异常,也可以处理从异常构造函数体中抛出的异常