条款8: 不要让异常逃离析构函数

举个例子:

class DBConnection
{
    public:
        ...
        static DBConnection create();

        void close();
};//这个class负责数据库连接。
//为了防止用户忘了close这个数据库连接,很容易想起来定义一个辅助类:
class DBCon{
    public:
        ..
        ~DBCon(){dbc.close();}
    private:
    DBConnection dbc;
}

close如果调用成功的情况下,是没问题的。但是如果调用导致异常的话,DBConn的析构函数会传播这个异常,导致不可预料的后果。

在析构函数中产生的异常通常按照两种方式来解决:

异常产生就结束:(这样可以防止不明确的行为带来的伤害)

DBConn::~DBConn()
{
    try{    dbc.close();  }catch(...){
       std:abort();
    }

}

或者是吞下这个异常:

DBConn::~DBConn(){
    try{
       dbc.close();
    }catch(...){
        //制作运转记录,表明调用的失败
    }
}

更好一点的解决方法是给DBConn自己也定义一个close函数,再用户不自己close的情况下在使用上面的做法,这样就给了用户一个处理异常的机会了:

class DBConn{
    public:
        ...
        void close()
        {
            db.close();
            close = true;
        }
        ~DBConn()
        {
            if(close == false){
                try{            dbc.close();         }catch(...){
                    std::abort();
                }
            }
        }
    private:
        bool close;
        DBConnection dbc;
};

小结:析构函数绝对不应该吐出异常,如果一个被析构函数调用的函数可能会抛出异常,析构函数应该捕捉他们然后再吞下他们,像前面的程序做的那样。

还有如果客户应该对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通的函数做这个操作,像上面的close那样。最后的析构函数中再做进一步的亡羊补牢

时间: 2024-12-29 11:13:57

条款8: 不要让异常逃离析构函数的相关文章

Effective C++_笔记_条款08_别让异常逃离析构函数

(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) C++并不禁止析构函数吐出异常,但它不鼓励你这样做.考虑如下代码: 1: class Widget{ 2: public: 3: ... 4: ~Widget() {...} //假设这个可能吐出一个异常 5: }; 6:  7: void doSomething() 8: { 9: vector<Widget> v ; //v在这里被自动销毁 10: ...

Effective C++ 条款八 别让异常逃离析构函数

class DBConn //这个class用来管理DBConnction对象 { public:   //自己设计一个新的DBConn接口 方法3 void close() { db.close(); closed = true; }     ~DBConn() //确保数据库连接总是会被关闭 { //db.close();   if (!closed) { try { db.close(); } catch() { //制作运转记录,记下对close的调用失 } } } protected:

条款8:别让异常逃离析构函数

例如: class Widget { public: ~Widget(){...} }; void doSomething() { vector<Widget>v; } 如果v中有10个Widget,销毁第一个时发生析构函数抛出异常,销毁第二个时析构函数又抛出异常,那么两个异常同时存在的情况下:程序要么结束执行要么导致不明确行为. 因此:析构函数绝对不要吐出异常.如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们或结束程序. 如果客户需要对某个操作函数运行期间抛出

Effective C++ Item 08-别让异常逃离析构函数

Item 08-别让异常逃离析构函数(Prevent exceptions from leaving destructors) C++并不禁止析构函数吐出异常,但它不鼓励你这样做.这是有理由的. Ex: class Widget{ public: ~Widget(){...}      //假设这个可能吐出一个异常 }; void doSomething() { std::vector<Widget> v; ...                                        

Effective C++ Item 8 别让异常逃离析构函数

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验1: 析构函数绝对不要吐出异常.如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序. 示例: class DBConnection{ public: static DBConnection create(); //返回DBConnection对象 void close(); }; class DBConn{ //这个class用来管理D

条款08:别让异常逃离析构函数

**在调用析构函数中出现的异常有两种方法: 一是调用abort强制结束程序:** 二是吞下异常: **更好的办法是: 针对某一个可能在析构函数中出现异常的部分,为用户提供该部分函数的调用放法从而给用户处理异常的机会:** 注意:

《Effective C++》——条款08:别让异常逃离析构函数

考虑如下代码: class Widget{ public: ... ~Widget(){...}//假设这个可能吐出一个异常 }; void doSomething() { std::vector<Widget>v; }//v在这里被销毁 当vector v被销毁,它有责任销毁其内含的所有Widgets.假设v内含十个Widgets,而在析构第一个元素期间,有个异常被抛出.其他九个Widgets还是应该被销毁,因此v应该调用它们各个析构函数.假设在调用期间,第二个Widget析构函数又抛出异常

别让异常逃离析构函数

前言 析构函数的作用在于完成对象销毁的一些“善后工作”,然而,某些不科学的设计会产生一些问题. 本文将说明其中的一种不科学设计 - "将异常处理机制设定在析构函数中" 会产生的问题,以及解决方案. 问题描述 首先,请看一下一段代码: 1 class Widget { 2 public: 3 //...... 4 ~Widget() { // 假定这个析构函数可能会吐出异常 5 //...... 6 } 7 //...... 8 }; 9 10 void doSomething () 1

EC笔记,第二部分:8.别让异常逃离析构函数

1.为何析构函数不应该抛出异常?    有两种情况:    1).假设析构函数中有众多语句,而第一条语句抛出异常(或者其他语句),那么抛出异常以后的语句就得不到执行.而通常我们在析构函数中写的是清理资源(或回收资源)的代码,那么部分资源就不会被回收,会造成内存泄漏或程序提前结束(abort的作用).    2).析构函数被调用的时间是在对象被销毁时,而我们很难知道(或者说没有刻意注意)对象何时被销毁,所以很难捕捉一个由析构函数抛出的异常(更别说处理了).2.两个并不高明的解决方案    1).在