一、未捕获异常:
如果没有任何一个层次的异常处理器能够捕获某种异常,则一个特殊的库函数terminate()(在头文件<exception>中定义)会被自动调用。默认情况下terminate()函数调用标准C库函数abort()使程序执行异常终止而退出。
abort()函数不会调用正常的终止函数,全局对象和静态对象的析构函数不会执行。
terminate()函数还会在如下两种情况下执行:
(1)局部对象的析构函数抛出异常时,栈正在进行清理工作,即栈反解的过程中。
(2)全局对象或静态对象的构造函数或析构函数抛出一个异常。
通过set_terminate()函数,可以设置自己的terminate()函数。
二、意外异常:
如果函数所抛出的异常,没有列在异常规格说明的异常集中,一个特殊的函数unexpected()将会被调用。默认的unexpected()函数会调用terminate()函数。
通过set_unexpected()函数可以设置自己的函数来响应意外的异常。
如果unexpected处理器所抛出的异常还不符合函数的异常规格说明,以下两种情况之一将会发生:
(1)如果函数的异常规格说明中包括std::bad_exception,unexpected处理器所抛出的异常会被替换成std::bad_exception对象,然后程序恢复到这个函数被调用的位置重新开始异常匹配。
(2)如果函数的异常规格说明中不包括std::bad_exception,程序会调用terminate()函数。
例子如下:
#include <iostream>
#include <stdlib.h>
using namespace std;
class A{};
class B{};
void my_thandler()
{
cout<<"terminate called"<<endl;
exit(0);
}
void my_uhandler1() {throw A();}
void my_uhandler2() {throw;}
void t() {throw B();}
void f() throw (A) {t();}
void g() throw(A,bad_exception) {t();}
int main()
{
set_terminate(my_thandler);
set_unexpected(my_uhandler1);
try
{
f();
}
catch(A&)
{
cout<<"caught an A from f"<<endl;
}
set_unexpected(my_uhandler2);
try
{
g();
}
catch(bad_exception&)
{
cout<<"caught a bad_exception from g"<<endl;
}
try
{
f();
}
catch(...)
{
cout<<"this will never print"<<endl;
}
return 0;
}
在上例中,f()声明抛出一个A类型的异常,但是t()缺抛出了一个B类型的异常,调用了用户设置的my_uhandler1,在其中抛出了一个A类型的异常,重新异常匹配,则匹配成功。
g()声明抛出A类型和std::bad_exception类型的异常,初次的异常匹配失败,调用了用户设置的my_uhandler2,其中把捕获到的异常重新抛出,此时仍然不符合g()的异常规格说明,但其中有std::bad_exception异常,故被替换为此类型的异常。
在第三部分中,f()抛出了异常规格说明中未声明的异常类型,故调用了my_thandler(),程序终止退出。