bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this

后端 未结 2 1383
清酒与你
清酒与你 2021-01-01 01:37

I have a base class which derives from boost::enable_shared_from_this, and then another class which derives from both the base class and boost::enable_shared_from_this:

相关标签:
2条回答
  • 2021-01-01 02:29

    You shouldn't inherit from enable_shared_from_this more than once in a given inheritance chain.

    In this case, you can leave the base class A inheriting from enable_shared_from_this, and have the derived class B return a shared_ptr<A> and then static_pointer_cast it to shared_ptr<B>.

    Or as Omnifarious pointed out, you could have a function in B which does this for you. Although, rather than overloading shared_from_this() I would favour explicitly-named functions to minimise surprises for clients of the class:

    #include <boost/enable_shared_from_this.hpp>
    #include <boost/shared_ptr.hpp>
    
    using boost::shared_ptr;
    
    class A : public boost::enable_shared_from_this<A> { };
    
    class B : public A {
    public:
        using enable_shared_from_this<A>::shared_from_this;
        shared_ptr<B> shared_B_from_this() {
            return boost::static_pointer_cast<B>(shared_from_this());
        }
        shared_ptr<B const> shared_B_from_this() const {
            return boost::static_pointer_cast<B const>(shared_from_this());
        }
    };
    
    int main() {
        shared_ptr<B> b = shared_ptr<B>(new B);
        shared_ptr<B> b1 = boost::static_pointer_cast<B>(b->shared_from_this());
        shared_ptr<B> b2 = b->shared_B_from_this();
        return 0;
    }
    
    0 讨论(0)
  • 2021-01-01 02:37

    Here's how I would solve your problem:

    #include <boost/enable_shared_from_this.hpp>
    #include <boost/shared_ptr.hpp>
    
    using namespace boost;
    
    class virt_enable_shared_from_this :
       public enable_shared_from_this<virt_enable_shared_from_this>
    {
     public:
       virtual ~virt_enable_shared_from_this() {}
    };
    
    template <class T>
    class my_enable_shared_from_this : virtual public virt_enable_shared_from_this
    {
     public:
       shared_ptr<T> shared_from_this() {
          return dynamic_pointer_cast<T>(virt_enable_shared_from_this::shared_from_this());
       }
    };
    
    class A : public my_enable_shared_from_this<A> { };
    
    class B : public my_enable_shared_from_this<B> { };
    
    class C : public A, public B, public my_enable_shared_from_this<C> {
     public:
       using my_enable_shared_from_this<C>::shared_from_this;
    };
    
    int main() {
       shared_ptr<C> c = shared_ptr<C>(new C());
       shared_ptr<C> c_ = c->shared_from_this();
    
       return 0;
    }
    

    This is painful and at least a bit ugly. But it works reasonably well, after a fashion. I think Fraser's idea of re-thinking your design is likely the better option.

    0 讨论(0)
提交回复
热议问题