别让异常逃离析构函数
2015-05-21 14:46
204 查看
c++中并不禁止析构函数吐出异常,但是并鼓励这样做,看下面代码:
![](https://images0.cnblogs.com/blog/742353/201505/211445297443055.png)
当vector v被销毁时,它有责任将其中所有的widgets销毁并且回收内存,而在析构第一个元素时候,析构函数会抛出异常,但是第二个vector的时候也会抛出异常,这对于c++来说太多了。这会导致程序不明确的行为。c++不喜欢析构函数吐出异常。
那么如果你的析构函数必须执行一个动作,而且该动作可能在失败时候抛出异常,怎么办?举个列子,class 负责数据库的链接:
![](https://images0.cnblogs.com/blog/742353/201505/211445309169512.png)
其中一个合理的解法是创建一个用来管理的DBConnecton资源的class,并在析构函数中调用close。如下:
![](https://images0.cnblogs.com/blog/742353/201505/211445324163771.png)
那么下面代码:
![](https://images0.cnblogs.com/blog/742353/201505/211445343382858.png)
只要调用close成功,就可以,但是如果该调用导致异常,DBConn析构函数就会传播异常,导致其离开析构函数,会出问题,抛出难以驾驭的问题。
怎么避免这个问题?DBConn的析构函数可以:
方法一:
![](https://images0.cnblogs.com/blog/742353/201505/211445359799158.png)
这个方法可以阻止异常从析构函数传播出去,不产生不明确的行为。abort可以抢先制不明确行为于死地。
方法二:
![](https://images0.cnblogs.com/blog/742353/201505/211445372607117.png)
以上的方法可行,但是都没有对抛出的异常而做出相应的反应。
那么我们可以从新来从新设计DBConn的接口:
![](https://images0.cnblogs.com/blog/742353/201505/211445386662348.png)
不让析构函数来抛出异常,让用户自己用时间来处理自己抛出的异常,从而达到不会因为析构函数抛出异常而导致出现不明的行为。
总结:
析构函数绝对不要吐出异常,如果一个析构函数调用,调用函数可能抛出异常的话,析构函数应该扑捉任何的异常,然后吞下他们(不传播),或者结束程序。
如果客户要对某个操作函数运行期间的异常作出反应,那么class应该提供了另一个普通的函数(而非在析构函数中)执行该操作。(该异常反正就是一句话,不能在析构函数中调用可能出现异常的函数,因为析构函数有可能多次被调用,那么抛出异常可能会出现不可以预知的结果,多以如果你想处理该异常的话,就应该自己定义一个普通的函数来处理该异常,就是自己来写一个接口,让用户自己来控制就可以。)
![](https://images0.cnblogs.com/blog/742353/201505/211445297443055.png)
当vector v被销毁时,它有责任将其中所有的widgets销毁并且回收内存,而在析构第一个元素时候,析构函数会抛出异常,但是第二个vector的时候也会抛出异常,这对于c++来说太多了。这会导致程序不明确的行为。c++不喜欢析构函数吐出异常。
那么如果你的析构函数必须执行一个动作,而且该动作可能在失败时候抛出异常,怎么办?举个列子,class 负责数据库的链接:
![](https://images0.cnblogs.com/blog/742353/201505/211445309169512.png)
其中一个合理的解法是创建一个用来管理的DBConnecton资源的class,并在析构函数中调用close。如下:
![](https://images0.cnblogs.com/blog/742353/201505/211445324163771.png)
那么下面代码:
![](https://images0.cnblogs.com/blog/742353/201505/211445343382858.png)
只要调用close成功,就可以,但是如果该调用导致异常,DBConn析构函数就会传播异常,导致其离开析构函数,会出问题,抛出难以驾驭的问题。
怎么避免这个问题?DBConn的析构函数可以:
方法一:
![](https://images0.cnblogs.com/blog/742353/201505/211445359799158.png)
这个方法可以阻止异常从析构函数传播出去,不产生不明确的行为。abort可以抢先制不明确行为于死地。
方法二:
![](https://images0.cnblogs.com/blog/742353/201505/211445372607117.png)
以上的方法可行,但是都没有对抛出的异常而做出相应的反应。
那么我们可以从新来从新设计DBConn的接口:
![](https://images0.cnblogs.com/blog/742353/201505/211445386662348.png)
不让析构函数来抛出异常,让用户自己用时间来处理自己抛出的异常,从而达到不会因为析构函数抛出异常而导致出现不明的行为。
总结:
析构函数绝对不要吐出异常,如果一个析构函数调用,调用函数可能抛出异常的话,析构函数应该扑捉任何的异常,然后吞下他们(不传播),或者结束程序。
如果客户要对某个操作函数运行期间的异常作出反应,那么class应该提供了另一个普通的函数(而非在析构函数中)执行该操作。(该异常反正就是一句话,不能在析构函数中调用可能出现异常的函数,因为析构函数有可能多次被调用,那么抛出异常可能会出现不可以预知的结果,多以如果你想处理该异常的话,就应该自己定义一个普通的函数来处理该异常,就是自己来写一个接口,让用户自己来控制就可以。)
相关文章推荐
- Effective C++笔记之五 别让异常逃离析构函数
- Effective C++ 08 别让异常逃离析构函数 笔记
- Effective C++学记之08 别让异常逃离析构函数
- Effective C++ Item 8 别让异常逃离析构函数
- EC读书笔记系列之4:条款8 别让异常逃离析构函数
- (7)别让异常逃离析构函数
- effect C++ 别让异常逃离析构函数
- Effective C++ Item 08-别让异常逃离析构函数
- effective c++ 别让异常逃离析构函数
- 《Effective C++》读书笔记:别让异常逃离析构函数
- Effective C++ .08 别让异常逃离析构函数
- 条款 08 别让异常逃离析构函数
- Effective C++ —— 别让异常逃离析构函数
- [Effective C++]条款08 别让异常逃离析构函数
- C++ 别让异常逃离析构函数
- Effective C++读书笔记之八:别让异常逃离析构函数
- 条款08 别让异常逃离析构函数
- 别让异常逃离析构函数
- Effective C++ 条款08 别让异常逃离析构函数
- Effective C++ -----条款08: 别让异常逃离析构函数