Как обрабатывать ошибки конструктора для 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();
  }
}   

Я знаю, что это не скомпилируется, но это должно показать принцип. Затем Фу становится...

class Foo
{
  Bar b;

  Foo()
  {
    DoSomething();
    b.f = UndoSomething; 
   ...     
  }
}

Обратите внимание, что теперь foo не требует деструктора. Звучит ли это как больше проблем, чем того стоит, или это уже обычная схема с чем-то полезным в ускорении, чтобы справиться с тяжелой работой для меня?

31
задан Roddy 5 July 2012 в 14:13
поделиться