Double inheritance of enable_shared_from_this

后端 未结 3 817
忘了有多久
忘了有多久 2021-01-02 05:34

I have an object (Z) which derives from two other objects (A and B).

A and B both derive from enable_shared_from_this<>, respectively enable

相关标签:
3条回答
  • 2021-01-02 06:20

    Using the shared_ptr aliasing constructor, a variation of ecatmur's answer can be derived:

    #include <memory>
    
    struct virtual_enable_shared_from_this_base:
       std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
       virtual ~virtual_enable_shared_from_this_base() {}
    };
    template<typename T>
    struct virtual_enable_shared_from_this:
    virtual virtual_enable_shared_from_this_base {
       std::shared_ptr<T> shared_from_this() {
          return std::shared_ptr<T>(
             virtual_enable_shared_from_this_base::shared_from_this(),
             static_cast<T*>(this));
       }
       std::shared_ptr<const T> shared_from_this() const {
          return std::shared_ptr<const T>(
             virtual_enable_shared_from_this_base::shared_from_this(),
             static_cast<const T*>(this));
       }
    };
    
    struct A: virtual_enable_shared_from_this<A> {};
    struct B: virtual_enable_shared_from_this<B> {};
    struct Z: A, B { };
    int main() {
       std::shared_ptr<Z> z = std::make_shared<Z>();
       std::shared_ptr<B> b = z->B::shared_from_this();
    }
    

    I expect this version to be faster in many circumstances, since it avoids a costly dynamic cast. However, as usual, only becnhmarks have the final word. Also, I have added the const variation.

    0 讨论(0)
  • 2021-01-02 06:27

    Yep, your class will be derived from two distinct classes enable_shared_from_this<A> and enable_shared_from_this<B>, and have two different weak ref's

    Trick from that answer allows to have one base class, because of virtual inheritance

    0 讨论(0)
  • 2021-01-02 06:28

    Yes, as per bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this the solution is to use virtual inheritance. Here's an implementation for the C++11 standard shared_ptr (not Boost):

    #include <memory>
    
    struct virtual_enable_shared_from_this_base:
       std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
       virtual ~virtual_enable_shared_from_this_base() {}
    };
    template<typename T>
    struct virtual_enable_shared_from_this:
    virtual virtual_enable_shared_from_this_base {
       std::shared_ptr<T> shared_from_this() {
          return std::dynamic_pointer_cast<T>(
             virtual_enable_shared_from_this_base::shared_from_this());
       }
    };
    
    struct A: virtual_enable_shared_from_this<A> {};
    struct B: virtual_enable_shared_from_this<B> {};
    struct Z: A, B { };
    int main() {
       std::shared_ptr<Z> z = std::make_shared<Z>();
       std::shared_ptr<B> b = z->B::shared_from_this();
    }
    

    This isn't part of the default implementation, probably because of the overhead of virtual inheritance.

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