views:

692

answers:

1

Imagine the following situation:

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;
   }
};

I want to attach an Alarm to a Device. Alarm and Device aren't allowed to know about each other (this would end up in circular dependency). So that's why I use the Interface Class IAlarm. Finally I want to be able to attach several alarms on to one device. The alarms can access the device they are attached to and the devices can start verification on the attached Alarms

Everything compiles nice. But if I try to attach an Alarm to a Device I get the following:

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

What's exactly the problem? This setup worked more or less before using boost::shared_ptr with references and pure pointers. Is it possible to get this work with boost:shared_ptr?

+5  A: 

The call to shared_from_this() is only valid if it is called on a dynamically allocated object that is owned by a shared_ptr (See the requirements listed in the docs). This means that there must exist a shared_ptr that owns the object, else shared_from_this() will not work.

Especially this means that you can't (successfully) call shared_from_this() in the constructor, since the object is just being constructed and is not yet owned by any shared_ptr instance.

To work around it you best move the code that attaches the alarm from the constructor to a separate method that gets called after the object is completely constructed:

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