异常的处理
析构函数抛出异常可被允许的:
class Widget
{
public:
...
~Widget() {...}
};
void doSomething()
{
std::vector<Widget> v;
...
}
如果v中包含多个元素, 当第一个元素在析构的过程中抛出异常,其余元素会不能释放而导致问题。 C++在析构的过程中不应该爆出异常。
假设使用一个class负责数据库的连接:
class DBConnection
{
public:
...
static DBConnection create();
void close();
};
为了确保客户不会忘记调用close函数, 我们创建一个用来管理DBConnection资源的class, 并在他的析构函数中调用close:
class DBConn
{
public:
...
~DBConn()
{
db.close();
}
private:
DBConnection db;
};
如果close函数调用成功, 一切正常, 如果调用失败,则异常会离开析构函数。 对于问题的处理, 我们有两个方法:
DBConn::~DBConn()
{
try
{
db.close();
}
catch(...)
{
std::abort();
}
}
或者不做处理, 吞下异常:
DBConn::~DBConn()
{
try
{
db.close();
}
catch(...)
{
}
}
如果程序遭遇了一个在析构期间发生的错误, 强迫结束程序是一个合理的选项, 而将异常吞下是一个不好的主意,这两个方法都不是很好的方法。
一个好的策略是我们可以重新设计DBCoon的接口, 使客户有机会对可能出现的问题作出反应,
class DBConn
{
public:
...
void close()
{
db.close();
closed = true;
}
~DBConn()
{
if(!closed)
{
try
{
db.close();
}
catch(...)
{
...
}
}
}
private:
DBConnection db;
bool closed;
};
把调用函数的责任从析构函数的手中移到客户的手上, 客户需要承担这个风险。
|