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:
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
using namespace boost;
class A : public enable_shared_from_this<A> { };
class B : public A , public enable_shared_from_this<B> {
public:
using enable_shared_from_this<B>::shared_from_this;
};
int main() {
shared_ptr<B> b = shared_ptr<B>(new B());
shared_ptr<B> b_ = b->shared_from_this();
return 0;
}
This compiles but at runtime it gives
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
Aborted
What is causing this, and is there some way around it?
EDIT:
What if I need something like this:
class A : public enable_shared_from_this<A> { };
class B : public enable_shared_from_this<B> { };
class C : public A, public B, public enable_shared_from_this<C> {
public:
using enable_shared_from_this<C>::shared_from_this;
};
such that A and B both need shared_from_this on their own (and one can't inherit it from the other), and C needs A, B, and shared_from_this?
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With