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

条款08:别让异常逃离析构函数
    (Prevent exception from leaving destructors).
   
内容:
    一般而言,只要析构函数抛出异常,程序就会可能过早结束或出现不确定行为,C++不喜欢析构函数吐
出异常!!那么我们如何避免呢?书上举的一个例子是:假设你使用一个class负责数据库连接:
    class DBConnection{
    public:
        ...
        static DBConnection create(); //get a DBConnection omit parameter for simplicity
        void close(); //close  DBConnection
    };
    为了防止客户使用完DBConnection以后忘记调用close(),我们可以创建一个新类DBConn来管理这个
对象,我们可以在这个新类的析构函数中调用该DBConnection对象的close();
    class DBConn{
    public:
        DBConn(DBConnection& db):db_(db){}
        ~DBConn(){
            db_.close();
        }
        ...
    private:
        DBConnection& db_;
    };
    我们就可以这样来用它:
    {
        DBConn connection(*(DBConnection.create()));
        ... //自动析构时候调用close方法
    }
    这里出现个问题就是如果db_.close();要是吐出异常怎么办?通常我们用以下解决方案:
    一是只要抛出异常就结束程序:
    DBConn::~DBConn(){
        try{
            db_.close();
        }catch(...){
            ....
            std::abort();//结束程序,可以强制"不明确行为"死掉
        }
    }
    二是吞掉异常:
    DBConn::~DBConn(){
        try{
            db_.close();
        }catch(...){
            ...
        }
    }
    一般而言吞掉异常不是很好的处理发式,但总比为"粗暴的结束程序"或"出现不明确行为"担负代价和风险
要好,这样即使程序遭遇了一个错误或者异常情况下都可以继续运行,在另一方面提高了软件的健状性.
    而这些解决方案都存在一个问题:客户不能对"close失败的异常情况"做出反应.为了解决这个问题,这里
我们可以将独立出来一个新的close接口:
    class DBConn{
    public:
        DBConn(DBConnection& db):db_(db){}
        void close(){
            db_.close();
            isClosed_ = true;
        }
        ~DBConn(){
            if(!isClosed_){
                //使用以上两种解决方案之一来进行解决.
            }           
        }
        ...
    private:
        DBConnection& db_;
        bool isClosed_;               
    };
    这样我们来重新审理这段代码,一个新的接口close(),提供给客户调用,如果出现异常客户可以第一
时间来进行处理,如果可以确定这里不会出现异常的话,也可以不处理,客户还可以选择不调用close(),
放弃对可能出现的异常处理,选择让析构函数自动调用.这样的设计你不觉得更加的合理吗?呵呵

    请记住:
    ▲ 析构函数绝对不要吐出异常.如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉异
常,然后吞下它们(不传播)或结束程序.
    ▲ 如果,客户需要对某个操作函数运行期间的异常做出反应,那么class应该提供一个普通函数(而非
在析构函数中)执行该操作.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值