《Effective C++》条款8:关于析构函数异常捕捉的问题
本章节主要描述了析构函数异常捕捉的问题;
对于C++来说,有一条重要的异常捕捉规定:所以异常都可以抛出,但是不可以在析构函数内进行传播;
所以对于析构函数,一定要注意异常问题,要么捕捉,要么强行结束;
但是由于程序强制结束并不科学,所以一边采用捕捉的方式来进行处理;
但是一旦出现异常,必定意味着程序的运行出现了问题,往往最好的办法还是先用普通函数判断,最后在析构函数进行异常捕捉;
对于典型的案例,有数据库连接的问题;
class DBConnection {
public:
static DBConnection create();
void close();
};
class DBConn {
public:
~DBConn() {
db.close();
}
private:
DBConnection db;
};
如上所示,典型的数据库连接问题,其中DBConnection为一个连接类,DBConn为控制类,控制DBConnection的连接和释放;
但是存在问题的是,db.close()可能会调用失败,所以根据析构函数异常捕捉原则,我们采用两种方法进行;
使用abort()来解决:
class DBConn {
public:
~DBConn() {
db.close();
std::abort();
}
private:
DBConnection db;
};
abort()的功能在于,如果抛出异常,不等异常传播,直接中断和结束所有程序运行;
这种方法比较无脑,违反了一般的程序逻辑控制思维;
使用try-catch来进行异常抓取:
class DBConn {
public:
~DBConn() {
try {
db.close();
}
catch(exception){
//对log日志进行记录,并且进行相关操作;
}
}
private:
DBConnection db;
};
类似的操作有点像JAVA中的操作,抓取异常并且进行处理;
个人疑惑点:
对于书中的一点意见不太理解,try_catch完全可以在catch中对后续行为做出定义,为什么不能进行补救措施?
也可以对接口进行优化,采用“双保险”措施:
书中给出的案例是采用两次操作判定来减少这类情况的产生;
例如,对于database的连接,完全可以先关一次,最后析构函数再关一次;
class DBConn {
public:
void close() {
db.close();
closed = true;
}
~DBConn() {
if (!closed) {
try {
db.close();
}
catch (exception) {
//继续log日志记录;
}
}
}
private:
DBConnection db;
bool closed;
};
s
针对于析构函数异常的捕捉,可以“对于析构函数中可能出现异常的操作,先定义普通成员函数进行操作,而后在析构函数中进行tray-catch二次判断”;

浙公网安备 33010602011771号