1

In the folowing example:

class A : public std::enable_shared_from_this<A> {
   
};

class B : public A {
    
};

can I use shared_from_this() in class B without any problems? I mean, is it necessary to derive directly from std::enable_shared_from_this, or can I derive indirecly by the use of a Base class which derives from it like in the above example?

I want to know if this logic works.

I am thinking that it might not work because std::enable_shared_from_this is sharing a pointer of object A not of object B. It might compile, but when run it can create undisered outputs.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185

2 Answers2

2

There is no problem deriving from a class which inherits from std::enable_shared_from_this. For example this code will work:

#include <memory>

class A : public std::enable_shared_from_this<A> {
public:   
    void bar()
    {
        auto a = shared_from_this();
    }
};

class B : public A {
public:
    void foo()
    {
        auto a = shared_from_this();
    }
};

int main()
{
    auto b = std::make_shared<B>();
    b->foo();
    b->bar();
}

Conversely deriving from std::enable_shared_from_this multiple times can lead to issues:

#include <memory>

class A : public std::enable_shared_from_this<A> {
public:   
    void bar()
    {
        auto a = shared_from_this();
    }
};

class B : public A, public std::enable_shared_from_this<B> {
public:
    void foo()
    {
        auto a = std::enable_shared_from_this<B>::shared_from_this();
    }
};

int main()
{
    auto b = std::make_shared<B>();
    b->foo();
    b->bar();
}

Now shared_from_this is ambiguous in B so we have to explicitly qualify it when we use it but worse it'll stop working properly: bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this

Note that you should add a virtual destructor to A to avoid potential pitfalls when destructing objects (though shared_ptr, when used correctly, does workaround this issue)

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
1

Yes, B publicly inherits everything from A, including its base classes.

That means that you can use shared_from_this() just as you would for an A (i.e. only on an instance that is owned by a shared pointer).

Note that we'll always get a pointer to A, not to the more derived class B. If we need to get a std::shared_ptr<B>, we'll need to down-cast using std::dynamic_pointer_cast(), or to also derive from std::enable_shared_from_this<B>.

Don't try to derive from multiple different enable_shared_from_this bases; instead, if we need B to return pointer-to-B, shadow the function:

    shared_ptr<B> B::shared_from_this() {
        return std::static_pointer_cast<B>(A::shared_from_this());
    }
Toby Speight
  • 27,591
  • 48
  • 66
  • 103