Я знаком с преимуществами RAII, но я недавно опробовал проблему в коде следующим образом:
class Foo
{
public:
Foo()
{
DoSomething();
...
}
~Foo()
{
UndoSomething();
}
}
Все отлично, за исключением того, что код в секции конструктора ...
выдал исключение, в результате чего UndoSomething()
никогда не вызывался.
Есть очевидные способы устранения этой конкретной проблемы, например wrap ...
в блоке 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 теперь не требует деструктора. Это звучит как больше неприятностей, чем стоит, или это уже общий шаблон с чем-то полезным в усилии для обработки тяжелой работы для меня?