我有一个派生自boost :: enable_shared_from_this的基类,然后是另一个派生自基类和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;
}
这会编译,但在运行时会给出
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
造成这种情况的原因是什么?有什么方法吗?
编辑:
如果我需要这样的东西怎么办:
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;
};
这样A和B都需要自己的shared_from_this(并且不能从另一个继承它),C需要A,B和shared_from_this?
答案 0 :(得分:7)
您不应该在给定的继承链中多次从enable_shared_from_this
继承。
在这种情况下,您可以保留从A
继承的基类enable_shared_from_this
,并让派生类B
返回shared_ptr<A>
,然后static_pointer_cast
它到shared_ptr<B>
。
或者正如Omnifarious指出的那样,你可以在B
中使用一个函数为你做这个。虽然,而不是重载shared_from_this()
,我倾向于明确命名的函数,以尽量减少该类客户端的意外:
#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;
}
答案 1 :(得分:4)
以下是我如何解决您的问题:
#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;
}
这很痛苦,至少有点难看。但经过时尚之后,它的效果相当不错。我认为Fraser重新思考你的设计的想法可能是更好的选择。