问题描述
c++不喜欢析构函数吐出异常(指不喜欢异常离开析构函数),但一个自定义析构函数又不得不执行某个可能失败的动作。
举个例子:某个数据库类
class DataBase{
public:
static DataBase create();
...
void close();
};
提问:为啥要static.....
为了确保用户调用了函数close,于是创建一个class来管理DB,把close写在了析构函数里:
class DBManage{
public:
...
~DBManage() {
db.close();
}
private:
DataBase db;
};
用户使用:建立一个原数据库对象,并交给manage类的对象来管理,对象调用析构函数时,就会关闭数据库
DBManage dbm(DataBase::create());
问题出现了:当DBManage的析构函数抛出异常时,会把异常传播出去。
解决方法(3种)
1. 修改析构函数——abort。当close抛出异常时就结束程序
DBManage::~DBManage() {
try { db.close();}
catch () {
...
std::abort();
}
}
2. 修改析构函数——吞下,即不传播出去
DBManage::~DBManage() {
try { db.close();}
catch () {
... // 仅仅记录异常, 不处理
// std::abort();
}
}
3. 修改整个DBManage接口 (better)
class DBManage{
public:
...
void close() {
db.close();
closed = true;
}
~DBManage() {
if (!closed) {
try { db.close();}
catch () {
... // 记录异常
}
}
}
private:
DataBase db;
bool closed;
};
解释:看起来好像是套了一环 ,在DBManage里面又写了 一个close去调用原close,但实际上是让客户自己去调用自己的close,将原来必须close的责任从DBM析构函数移到了使用DBM的客户手上。