规则一 析构函数绝对不要吐出异常
如果析构函数中的某些操作可能导致异常,就记得捕捉异常。
class DBConn {
public:
...
~DBConn() {
try {db.close();}
catch (...) {
// 制作运转纪录,记下对close的调用失败
// 终止程序,析构函数不要吐出异常
std::abort();
}
}
};
规则二 将异常处理转移给用户
class DBConn {
public:
...
void close() { // 提供用户使用的新函数
db.close();
closed = true;
}
~DBConn() {
if (!closed) {
try { // 双重保险,如果用户忘记关闭连接的话
db.close();
}
catch (...) { // 如果关闭动作失败,记录下来并结束程序或吞下异常
// 制作运转记录,记下对close的调用失败;
...
}
}
}
private:
DBConnection db;
bool closed;
};
提供给用户新的函数调用,这样就可以把异常处理转交给用户,再析构函数中还需再次捕捉异常,是为了双重保险。
总结
- 析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数就应该捕捉任何异常,然后吞下它们(不传播)或者结束程序。
- 如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作。