私は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はデストラクタを必要としないことに注意してください。それは価値があるよりも厄介なように聞こえますか、それともこれは私にとって重い持ち上げを処理するためのブーストに役立つ何かを備えたすでに一般的なパターンですか?