欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-08 10:20:36
...

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应提供一个普通函数(而非在析构函数中)执行该操作。