c++中并不禁止析构函数吐出异常,但是并鼓励这样做,看下面代码:
当vector v被销毁时,它有责任将其中所有的widgets销毁并且回收内存,而在析构第一个元素时候,析构函数会抛出异常,但是第二个vector的时候也会抛出异常,这对于c++来说太多了。这会导致程序不明确的行为。c++不喜欢析构函数吐出异常。
那么如果你的析构函数必须执行一个动作,而且该动作可能在失败时候抛出异常,怎么办?举个列子,class 负责数据库的链接:
其中一个合理的解法是创建一个用来管理的DBConnecton资源的class,并在析构函数中调用close。如下:
那么下面代码:
只要调用close成功,就可以,但是如果该调用导致异常,DBConn析构函数就会传播异常,导致其离开析构函数,会出问题,抛出难以驾驭的问题。
怎么避免这个问题?DBConn的析构函数可以:
方法一:
这个方法可以阻止异常从析构函数传播出去,不产生不明确的行为。abort可以抢先制不明确行为于死地。
方法二:
以上的方法可行,但是都没有对抛出的异常而做出相应的反应。
那么我们可以从新来从新设计DBConn的接口:
不让析构函数来抛出异常,让用户自己用时间来处理自己抛出的异常,从而达到不会因为析构函数抛出异常而导致出现不明的行为。
总结:
析构函数绝对不要吐出异常,如果一个析构函数调用,调用函数可能抛出异常的话,析构函数应该扑捉任何的异常,然后吞下他们(不传播),或者结束程序。
如果客户要对某个操作函数运行期间的异常作出反应,那么class应该提供了另一个普通的函数(而非在析构函数中)执行该操作。(该异常反正就是一句话,不能在析构函数中调用可能出现异常的函数,因为析构函数有可能多次被调用,那么抛出异常可能会出现不可以预知的结果,多以如果你想处理该异常的话,就应该自己定义一个普通的函数来处理该异常,就是自己来写一个接口,让用户自己来控制就可以。)