C++箴言:防止因异常而离开析构函数

C++箴言:防止因异常而离开析构函数,第1张

C++箴言:防止因异常而离开析构函数,第2张

C++并不禁止从析构函数抛出异常,但确实阻碍了实践。至于任何好的理由,请考虑:

类小部件{
public:
...
~Widget() {...} //假设这可能会发出异常
};

void do something()
{
STD::vector v;
...
} // v在这里自动销毁

当vector v被析构时,它负责销毁它包含的所有小部件。假设v中有十个小部件,销毁第一个时抛出异常。其他9个小部件仍然必须被销毁(否则它们持有的任何资源都会被泄漏),所以V应该调用它们的析构函数。但是假设在这个调用中,第二个小部件的析构函数抛出了另一个异常。现在同时有两个异常活动,这对于C++来说太多了。当这两个同时发生的异常在非常巧合的条件下发生时,程序的执行将终止或导致未定义的行为。在本例中,将引发未定义的行为。同样,使用任何标准库容器(例如list、set),TR1中的任何容器,甚至数组,都可能导致未定义的问题。你不一定要成为一个容器或者一个数组才会有麻烦。程序的死的或未定义的行为是析构函数抛出异常的结果,即使没有使用容器或数组。++C不喜欢抛出异常的析构函数。这很容易理解,但是如果你的析构函数需要执行一个可能失败并抛出异常的操作呢?例如,假设您使用一个数据库连接类:

类db connection {
public:
...

静态db connection create();//函数返回
// DBConnection对象;params
//为简单起见省略

void close();//关闭连接;抛出一个
};//关闭失败异常

为了确保客户不会忘记调用DBconnection对象的close,一个合理的想法是为DBConnection设置一个资源管理类,并在其析构函数中调用close。这样的资源管理类将在以后的文章中探讨,但在这里,只要想想这样的类的析构函数是这样的就够了:

类DBConn { //用于管理DBConnection的类
public: // objects
...
~DBConn() //确保数据库连接
{ //始终关闭
db . close();
}
private:
db connection db;
};

它允许客户这样编程:

{
//打开一个block
DBConn DBC(db connection::create());//创建DBConnection对象
//并将其交给DBConn
//对象来管理
...//通过DBConn接口
} //使用DBConnection对象
//在块结束时,DBConn
//对象被销毁,从而
//自动调用关闭
//db connection对象

如果能成功调用close就好了,但是如果这个调用导致了异常,DBConn的析构函数就会传播那个异常,也就是说会离开析构函数。这就产生了一个问题,因为析构函数抛出了一个烫手山芋。

有两种主要方法可以避免这种麻烦。Dbc的析构函数可以:

终止程序。如果close抛出异常,调用abort。

DBConn::~ DBConn()
{
try { db . close();}
catch(...){
创建关闭调用失败的日志条目;
STD::abort();
}
}

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » C++箴言:防止因异常而离开析构函数

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情