在我的析构函数中,我必须清理一些资源。假设我有三次调用以清除可能抛出的资源。因为让异常离开析构函数不好,我的设计模式应该是什么?显然,下面的方式不可扩展。
感谢。
class B::~B(){
try{
clearResourceA()
}
catch{
try{
clearResourceB();
}
catch{
clearResourceC();
}
clearResourceC();
}
clearResourceB();
.
.
}
答案 0 :(得分:10)
为什么不:
try{clearResourceA();} catch(...){}
try{clearResourceB();} catch(...){}
try{clearResourceC();} catch(...){}
答案 1 :(得分:5)
将每个资源封装在一个类中,该类在其析构函数中清除它们(使用周围的try / catch):
struct ProperlyManagedA {
// some means of using the resource - a rudimentary way is this:
A &getA() { return a; }
const A &getA() const { return a; }
// cleanup
~ProperlyManagedA() {
try {
a.clear(); // whatever it is ClearResourceA actually does
} catch (...) {}
}
private:
A a;
}
带有自定义删除器的shared_ptr
是实现此目的的一种方法,无需为每种类型的资源创建整个类。
根据丢弃的内容,您可以改进以丢弃异常(例如记录问题)。
更好的是,修改资源A,B和C,以便他们在自己的析构函数中清除自己。但这可能是不可能的。
无论哪种方式,您都可以根据需要将尽可能多的此类资源放在一个类中,而无需向类的析构函数添加任何代码。这是“可扩展性”。 RAII的重点是,资源的每个用户都不必编写清理代码才能正确使用资源。
答案 2 :(得分:2)
使用catch-all(即catch(...))捕获任何可以抛出析构函数的东西,并尽力处理抛出的异常。确保没有异常从析构函数中传播出来,catch-all将帮助您防止。
答案 3 :(得分:2)
您还可以包装ClearResources函数以确保它们永远不会抛出。他们为什么还要扔?
答案 4 :(得分:1)
因为您询问了设计模式我将告诉我成功使用的经验法则。 所有具有清理/终止功能的功能都应从不抛出。
这些功能通常是公认的名称:
这背后的理由是:
我可以尝试使用RAII pattern。但即使在这种情况下,上述规则也将被使用。
答案 5 :(得分:0)
try
{
ClearResourceA();
}
catch(...)
{
ExceptionWasThrown();
}
try
{
ClearResourceB();
}
catch(...)
{
ExceptionWasThrown();
}
...