【发布时间】:2012-07-05 23:09:43
【问题描述】:
我熟悉 RAII 的优点,但我最近在这样的代码中遇到了一个问题:
class Foo
{
public:
Foo()
{
DoSomething();
...
}
~Foo()
{
UndoSomething();
}
}
一切正常,除了构造函数 ... 部分中的代码抛出异常,导致 UndoSomething() 从未被调用。
有一些明显的方法可以解决这个特定问题,例如将 ... 包装在一个 try/catch 块中,然后调用 UndoSomething(),但是 a: 那是重复代码,而 b: try/catch 块是一种代码味道我尝试通过使用 RAII 技术来避免。而且,如果涉及多个 Do/Undo 对,代码可能会变得更糟,更容易出错,我们必须中途清理。
我想知道有更好的方法来做到这一点 - 也许一个单独的对象接受一个函数指针,并在它被破坏时调用该函数?
class Bar
{
FuncPtr f;
Bar() : f(NULL)
{
}
~Bar()
{
if (f != NULL)
f();
}
}
我知道这不会编译,但它应该显示原理。 Foo 然后变成...
class Foo
{
Bar b;
Foo()
{
DoSomething();
b.f = UndoSomething;
...
}
}
请注意, foo 现在不需要析构函数。这听起来比它的价值更麻烦,还是这已经是一种常见的模式,在 boost 中为我处理繁重的工作提供了有用的东西?
【问题讨论】:
-
try/catch 是 not 代码异味,并且经常未被充分利用 IMO。
-
@MooingDuck:确实,它们本身没有气味。但是
try {} catch(...) {throw;}的气味比较重。