2015-05-27 2 views
2

Я читал некоторые сообщения на форуме, написанные давно, и столкнулись с проблемой, как это:вызов функции обратного вызова, когда объект будет уничтожен

Как создать объект такой, что вы можете передать функцию обратного вызова к нему, и когда объект уничтожается, функция обратного вызова всегда выполняется?

Я знаю, что эта функция обратного вызова должна быть помещена в деструктор с RAII. И у кого-то есть код решения этой проблемы, как указано ниже:

class MyClass { 
    public: 
    MyClass(void (*cb)()) : done(cb) {} 
    ~MyClass() { 
     if (done) { 
     try { 
      (*done)(); 
     } 
     catch (...) { 
      // choice of exit, log, throw an alert to somewhere in the 
      //system, or ignore 
     } 
    } 
    } 
private: 
void (*done)(); 
}; 

Но как-то я не чувствую себя комфортно с этим кодом.

  1. Поскольку часто советуют не throw в деструкторе, но это нормально здесь, по крайней мере в этом коде, так как весь try, catch блок находится внутри деструктора?
  2. Каким-то образом я чувствую, что нецелесообразно разыменовывать указатель в деструкторе, поскольку объект, на который указывает указатель, может быть в недопустимом состоянии во время разворачивания стека, когда еще есть еще одно исключение. Но в этом коде функция, на которую указывает функция, является функцией-членом, а в деструкторе проверяется этот указатель, так что это нормально в этом случае?
  3. Есть ли лучшее решение, чем этот код?
+0

Err, деструктор * это * а Перезвони. – EJP

+0

"*, поскольку объект, на который указывает указатель, может находиться в недопустимом состоянии во время разворачивания пакета, когда еще есть еще одно исключение *" - обратный вызов в этом примере принимает только отдельную функцию, а не объект, поэтому нет состояния объекта беспокоиться о. С другой стороны, обратный вызов может осуществлять внутренний доступ к другим объектам, но это другое дело. –

+0

@RemyLebeau, вы думаете, это нормально, если деструктор вызывает указатель на функцию, который не является членом класса? – Allanqunzi

ответ

2

Правил не допустить какие-либо исключения побега деструктора.

Ваш деструктор может получать исключения и даже исключать исключения, если они пойманы до конца деструктор-метода. Так что просто поймайте все до конца.

Я не вижу ничего плохого в разыменовании указателя в dtor. Это то же, что и любой другой метод с одинаковыми рисками. (так что планируйте заранее, чтобы вы не разыменовали NULL или недопустимый указатель).

Ваш код выглядит довольно хорошо для меня.
я бы указать на отсутствие виртуального dtor, и в зависимости от деталей, вы можете захотеть сделать член сделалзащищенный член вместо частного

Смежные вопросы