Использование boost :: shared_ptr в иерархии наследования - PullRequest
4 голосов
/ 11 сентября 2009

Представьте себе следующую ситуацию:

class IAlarm : public boost::enable_shared_from_this<IAlarm>  {
   boost::shared_ptr<IAlarm> getThisPointerForIAlarm() {
      return shared_from_this();
   }

   void verifyThis(int); // called by Device
};

class Alarm : public IAlarm {
   Alarm( boost::shared_ptr< Device >  attachedDevice){
      attachedDevice->attachAlarm(this->getThisPointerForIAlarm());
   }

   void sendAlarm(){
      attachedDevice->Alarm();
   } 

};

class Device {
   attachAlarm( boost::shared_ptr< IAlarm > ia){
      this->alarm=ia;
   }
};

Я хочу прикрепить сигнал тревоги к устройству. Alarm и Device не могут знать друг о друге (это может привести к циклической зависимости). Вот почему я использую интерфейсный класс IAlarm. Наконец, я хочу иметь возможность подключить несколько сигналов тревоги к одному устройству. Аварийные сигналы могут получить доступ к устройству, к которому они подключены, и устройства могут начать проверку на подключенных Аварийных сигналах

Все хорошо компилируется. Но если я пытаюсь подключить сигнал тревоги к устройству, я получаю следующее:

boost::shared_ptr<Device> ptrDevice(new Device());
boost::shared_ptr<IAlarm> ptrAlarm(new Alarm( ptrDevice ));

    terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_weak_ptr> >'

  what():  tr1::bad_weak_ptr

В чем проблема? Эта настройка работала более или менее перед использованием boost::shared_ptr со ссылками и чистыми указателями. Можно ли получить эту работу с boost:shared_ptr?

1 Ответ

15 голосов
/ 11 сентября 2009

Вызов shared_from_this() действителен только в том случае, если он вызывается для динамически размещенного объекта, которому принадлежит shared_ptr (см. Требования , перечисленные в документации ). Это означает, что должен существовать shared_ptr, которому принадлежит объект, иначе shared_from_this() не будет работать.

В особенности это означает, что вы не можете (успешно) вызвать shared_from_this() в конструкторе, так как объект только создается и еще не принадлежит ни одному экземпляру shared_ptr.

Чтобы обойти это, лучше всего переместить код, который присоединяет сигнал тревоги от конструктора, к отдельному методу, который вызывается после того, как объект полностью построен:

boost::shared_ptr<Alarm> a(new Alarm());
a->attach(attachedDevice);
...