Search code examples
c++boostshared-ptrweak-references

bad_weak_ptr when calling shared_from_this() in base class


I have a SuperParent class, a Parent class (derived from SuperParent) and both contain a shared_ptr to a Child class (which contains a weak_ptr to a SuperParent). Unfortunately, I'm getting a bad_weak_ptr exception when trying to set the Child's pointer. The code is the following:

#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

using namespace boost;

class SuperParent;

class Child {
public:
    void SetParent(shared_ptr<SuperParent> parent)
    {
        parent_ = parent;
    }
private:
    weak_ptr<SuperParent> parent_;
};

class SuperParent : public enable_shared_from_this<SuperParent> {
protected:
    void InformChild(shared_ptr<Child> grandson)
    {
        grandson->SetParent(shared_from_this());
        grandson_ = grandson;
    }
private:
    shared_ptr<Child> grandson_;
};

class Parent : public SuperParent, public enable_shared_from_this<Parent> {
public:
    void Init()
    {
        child_ = make_shared<Child>();
        InformChild(child_);
    }
private:
    shared_ptr<Child> child_;
};

int main()
{
    shared_ptr<Parent> parent = make_shared<Parent>();
    parent->Init();
    return 0;
}

Solution

  • This is because your Parent class inherits enable_shared_from_this twice. Instead, you should inherit it once - through the SuperParent. And if you want to be able to get shared_ptr< Parent > within Parent class, you can inherit also it from the following helper class:

    template<class Derived> 
    class enable_shared_from_This
    {
    public:
    typedef boost::shared_ptr<Derived> Ptr;
    
    Ptr shared_from_This()
    {
        return boost::static_pointer_cast<Derived>(static_cast<Derived *>(this)->shared_from_this());
    }
    Ptr shared_from_This() const
    {
        return boost::static_pointer_cast<Derived>(static_cast<Derived *>(this)->shared_from_this());
    }
    };
    

    Then,

    class Parent : public SuperParent, public enable_shared_from_This<Parent>