引发异常时编译器总是创建一个临时拷贝,即使异常规范和catch块中指定的是引用。例如,请看下面的代码
class problem {...};
...
void super() throw (problem)
{
...
if (oh_no)
{
problem oops; // construct object
throw oops; // throw it
...
}
...
try {
super();
}
catch(problem & p)
{
// statements
}
p将指向oops的副本而不是oops本身。这是件好事,因为函数super()执行完毕后,oops将不复存在。顺便说一句,将引发异常和创建对象组合在一起将更简单
throw problem(); // construct and throw default problem object
基类引用可以执行派生类对象。假设有一组通过继承关联起来的异常类型,则在异常规范中只需列出一个基类引用,它将与任何派生类对象匹配。
假设有一个异常类层次结构,并要分别处理不同的异常类型,则使用基类引用将能够捕获任何异常对象;而使用派生类对象只能捕获它所属类及从这个类派生而来的类的对象。引发的异常对象将被第一个与之匹配的catch块捕获。这意味着catch块的排列顺序应该与派生顺序相反
class bad_1 {...};
class bad_2 : public bad_1 {...};
class bad_3 : public bad 2 {...};
...
void duper()
{
...
if (oh_no)
throw bad_1();
if (rats)
throw bad_2();
if (drat)
throw bad_3();
}
...
try {
duper();
}
catch(bad_3 &be)
{ // statements }
catch(bad_2 &be)
{ // statements }
catch(bad_1 &be)
{ // statements }
提示:
如果有一个异常类继承层次结构,应这样排列catch块: 将捕获位于层次结构最下面的异常类的catch语句放在最前面,将捕获基类异常的catch语句放在最后面。