假设现在我们有一个类Widget
class Widget{
public:
...;
~Widget() {
// 这里抛出异常了
...;
}
};
然后我们创建一个Widget类型的的vector数组
int main(){
std::vector<Widget> v;
}
假设现在v的生命周期结束了,它会析构掉里面的所有Widget对象
然而此时,析构第一个Widget对象时抛出了异常。为了防止内存泄露,我们依然要保证后面的其他所有Widget对象被析构。
但很不幸的是,析构第二个Widget时又抛出了一个异常。那么此时编译器抛出了两个异常。对于c++而言抛出两个异常是非常危险的,这会导致程序执行不明确行为。具体为什么在More Effective里有讲到,这里只需知道c++不喜欢析构函数抛出异常即可
书上告诉我们:交给用户
考虑这个数据库管理类
class DBConnection;
class DBConn{
public:
~DBConn(){
db.close();
}
private:
DBConnection db;
};
DBConnection是一个数据库连接类,它有一个close方法,这个方法会抛出异常。我们希望设计一个新的类DBConn来管理数据库的连接与释放。也就是当DBConn对象析构时,自动关闭数据库连接。
但是很遗憾close这个方法会抛出异常。那么我们需要重新设计接口,提供一个普通函数(非析构)给用户,然他自己释放。如果用户也忘了,那才交给析构函数释放。如果这时候还出问题了,那就听天由命吧。不是所有的问题都有完美的解决方法的!
class DBConn{
public:
// 给用户提供的普通函数来关闭连接
void close(){
db.close();
closed = true;
}
~DBConn(){
if (!closed) { // 如果用户也忘了,就让析构函数来
try{
db.close();
}
catch (...) { // 很不幸析构时抛出了异常
// 要么记录下来,结束程序 std::abort()
// 要么吞掉
}
}
}
private:
DBConnection db;
bool closed;
}
原文:https://www.cnblogs.com/destinyzk/p/14955984.html