◆ 1、当catch语句捕获一个异常后,可能不能完全处理异常,完成某些操作后,该异常必须由函数链中更上级的函数来处理,这时catch子句可以
重新抛出
(rethrow)该异常,把异常传递给函数调用链中更上级的另一个catch子句,由它进行进一步处理。
重新抛出表达式仍为: throw;
但仅有一个关键字,因为异常类型在catch语句中已经有了,不必再指明。
被重新抛出的异常就是原来的异常对象。但是重新抛出异常的catch子句应该把自己做过的工作告诉下一个处理异常的catch子句,往往要对异常对象做一定修改,以表达某些信息,因此catch子句中的异常声明必须被声明为引用,这样修改才能真正做在异常对象自身中。
◆ 2、通用catch子句(catch_all):
catch(...)
{/*代码*/}
任何异常都可以进入这个catch子句。这里的三个点称为省略号。花括号中的复合语句用来执行指定操作。
异常发生后按栈展开(stack unwinding)退出,动态分配的非类对象资源不会自动释放的,通常在catch_all子句中释放。例如:
void fun1()
{
int *res;
res=new int[100]; //定义一个资源对象
try{
//代码包括使用资源res和某些可能引起异常抛出的操作
} //异常可能有多种
catch(...)//不论是那种异常都在此释放
{
delete [] res; //释放资源对象res
throw; //重新抛出异常
}
delete [] res; //正常退出前释放资源对象res;
}
◆ 3、 catch_all子句 可以单独使用,也可以与其它catch子句联合使用。如果联合使用,它必须放在相关catch子句表的最后。
catch子句被检查的顺序与它们在try块之后排列顺序相同,一旦找到了一个匹配,则后续的catch子句将不再检查,按此规则,catch_all子句(catch(...){})处理表前面所列各种异常之外的异常。
如果只用catch_all子句进行某项操作,则其他的操作应由catch子句重新抛出异常,逆调用链去查找新的处理子句来处理,不能在子句列表中再安排一个处理同一异常的子句,因为第二个子句是永远执行不到的。
重新抛出表达式仍为: throw;
但仅有一个关键字,因为异常类型在catch语句中已经有了,不必再指明。
被重新抛出的异常就是原来的异常对象。但是重新抛出异常的catch子句应该把自己做过的工作告诉下一个处理异常的catch子句,往往要对异常对象做一定修改,以表达某些信息,因此catch子句中的异常声明必须被声明为引用,这样修改才能真正做在异常对象自身中。
◆ 2、通用catch子句(catch_all):
catch(...)
{/*代码*/}
任何异常都可以进入这个catch子句。这里的三个点称为省略号。花括号中的复合语句用来执行指定操作。
异常发生后按栈展开(stack unwinding)退出,动态分配的非类对象资源不会自动释放的,通常在catch_all子句中释放。例如:
void fun1()
{
int *res;
res=new int[100]; //定义一个资源对象
try{
//代码包括使用资源res和某些可能引起异常抛出的操作
} //异常可能有多种
catch(...)//不论是那种异常都在此释放
{
delete [] res; //释放资源对象res
throw; //重新抛出异常
}
delete [] res; //正常退出前释放资源对象res;
}
◆ 3、 catch_all子句 可以单独使用,也可以与其它catch子句联合使用。如果联合使用,它必须放在相关catch子句表的最后。
catch子句被检查的顺序与它们在try块之后排列顺序相同,一旦找到了一个匹配,则后续的catch子句将不再检查,按此规则,catch_all子句(catch(...){})处理表前面所列各种异常之外的异常。
如果只用catch_all子句进行某项操作,则其他的操作应由catch子句重新抛出异常,逆调用链去查找新的处理子句来处理,不能在子句列表中再安排一个处理同一异常的子句,因为第二个子句是永远执行不到的。