Я знаком с преимуществами 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();
}
}
Я знаю, что это не скомпилируется, но это должно показать принцип. Затем Фу становится...
class Foo
{
Bar b;
Foo()
{
DoSomething();
b.f = UndoSomething;
...
}
}
Обратите внимание, что теперь foo не требует деструктора. Звучит ли это как больше проблем, чем того стоит, или это уже обычная схема с чем-то полезным в ускорении, чтобы справиться с тяжелой работой для меня?