Effective C++ (学习笔记详解08)

加班学习使我快乐哈哈哈加油啊小朋友假期学习使我快乐哈哈哈~加油啊小朋友痛并快乐着!!

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

如果析构函数必须执行一个动作,而该动作可能会在失败时抛出异常,例如

class DBConn{      //class 用来管理DBConnetive对象
public:
  ~DBConn(){       //确保db总能被关闭。但是一旦调用产生异常,析构函数就会传播该异常
    db.close();
  }
private:
    DBConnetive db;
};

两个办法避免该问题。DBConn的析构函数可以:

1、如果close抛出异常就结束程序。通常通过调用abort完成:

DBConn::~DBConn
{
  tr{ db.close(); }
  catch(...)
  { 
      //记下close调用失败
      std::abort(); 
  }
}

如果程序遭遇一个“于析构期间发生的错误”后无法继续执行,“强迫结束程序”是个合理选项。毕竟它可以阻止异常从析构函数传播出去(那会导致不明确的行为)。也就是说调用abort可以抢先制“不明确行为”于死地。

2、吞下因调用close而发生的异常

DBConn::~DBConn
{
  try{ db.close(); }
  catch(...)
  { 
      //记下close调用失败
  }
}

一般而言,将异常吞掉是个坏主意,因为它压制了“某些动作失败”的重要信息!然而有时候吞下异常也比负担“草率结束程序”或“不明确行为带来的风险”好。为了让这成为一个可行方案,程序必须能够继续可靠地执行,即使在遭遇并忽略个错误之后。

以上两种做法都无法对“导致close抛出的异常”做出反应。

**解决办法:重新设计DBConn接口,使其客户有机会对可能出现的问题作出反应。

class DBConn{
public:
  void close(){                          //供使用的新函数
    db.close();
    closed = true;
  }
  ~DBConn(){
    if( !closed ){
      try{db.close(); }                  //关闭连接
      catch(...){     //记下close调用失败 }
    }
  }
private:
  bool closed;
};
  • 不要让析构函数抛出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,并不让他们继续传播(吞下他们或结束程序)。
  • 如果需要对某个操作函数运行期抛出的异常做回应,则class应提供一个普通函数(而非在析构函数中)执行该操作。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值