我熟悉RAII的優點,但我最近絆倒了一個問題,像這樣的代碼:如何處理構造失敗的RAII
class Foo
{
public:
Foo()
{
DoSomething();
...
}
~Foo()
{
UndoSomething();
}
}
一切都很好,除了在構造...
節代碼拋出異常,結果UndoSomething()
從未被調用過。
有固定的特定問題,就像在一個try/catch塊,然後調用UndoSomething()
包裝...
的明顯的方式,而是:這是複製代碼,和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現在不需要析構函數。這聽起來像是比它的價值更麻煩,還是這已經是一種常見的模式,有助於處理我的繁重工作?
try/catch是_not_代碼味道,並經常被使用IMO。 – 2012-07-05 14:20:44
看這裏:http://www.parashift.com/c++-faq-lite/selfcleaning-members.html – MadScientist 2012-07-05 14:22:11
@MooingDuck:的確,他們本身並沒有味道。但是'try {} catch(...){throw;}'有相當強烈的氣味。 – 2012-07-05 14:56:49