16.3.5 析构函数中可否抛出异常
对局部类对象来说,如果成员函数中抛出异常,在处理该异常之前,该对象要先进行析构,才开始执行匹配catch块,可如果在析构函数中也抛出了异常,会出现不可预料的错误,如示例代码16.13所示。
代码16.13 析构函数中抛出异常ThrowByADestructor
<———————————文件名:example1613.cpp———————————————-> 01 #include<iostream> 02 using namespace std; 03 void Myterminate()//自定义Myterminate函数 04 { 05 cout<<"错误,退出"<<endl; 06 exit(0); 07 } 08 void(*old)()=set_terminate(Myterminate);//用自定义的Myterminate函数替代原有库函数 09 class Ex 10 { 11 public: 12 void fun()//成员函数中抛出异常 13 { 14 throw"Error in fun()"; 15 } 16 ~Ex()//析构函数中同样抛出异常 17 { 18 throw 0; 19 } 20 }; 21 int main() 22 { 23 try 24 { 25 Ex e; 26 e. fun(); 27 } 28 catch(……)//可接收任何类型的异常 29 { 30 cout<<"Hello"<<endl; 31 } 32 return 0; 33 }
输出结果如下所示。
错误,退出
【代码解析】代码的输出结果有些出人意料,尽管采用了省略号catch块,看起来应该能够捕获所有异常,但结果是terminate函数总是会被调用,这是因为两个异常接连被抛出的缘故,当第26行“e.fun();”中抛出异常时,根据堆栈解退机制,自动类对象e将会被撤销,其析构函数被执行,即代码第16行,此时又将抛出一个新的异常,在这种情况下,terminate函数将被执行。
技巧除非特殊需要,不推荐在析构函数中抛出异常,否则,这很有可能成为程序的致命伤。