enable_shared_from_this用法

enable_shared_from_this用法

转载 2014年05月12日 21:49:17

·        标签:

·        c++ /

·        enable_shared_from_t

·        905

shared_from_this()enable_shared_from_this<T>的成员函数,返回shared_ptr<T>。首先需要注意的是,这个函数仅在shared_ptr<T>的构造函数被调用之后才能使用。原因是enable_shared_from_this::weak_ptr并不在构造函数中设置,而是在shared_ptr<T>构造函数中设置。 

如下代码是错误的:

1.    classD:public boost::enable_shared_from_this<D>

2.    {

3.    public:

4.        D()

5.        {

6.           boost::shared_ptr<D> p=shared_from_this();

7.        }

8.    };

复制代码

因很简单,在D的构造函数中虽然可以保证enable_shared_from_this<D>的构造函数已经被调用,但正如前面所说,weak_ptr还没有设置。 

如下代码也是错误的:

1.    class D:public boost::enable_shared_from_this<D>

2.    {

3.    public:

4.        void func()

5.        {

6.           boost::shared_ptr<D> p=shared_from_this();

7.        }

8.    };

9.    void main()

10.  {

11.     D d;

12.     d.func();

13.  }

复制代码

误原因同上。 

如下代码是正确的:

1.    void main()

2.    {

3.        boost::shared_ptr<D> d(new D);

4.        d->func();

5.    }

复制代码

boost::shared_ptr<D> d(new D)实际上执行了3个动作:首先调用enable_shared_from_this<D>的构造函数;其次调用D的构造函数;最后调用 shared_ptr<D>的构造函数。是第3个动作设置了enable_shared_from_this<D> weak_ptr,而不是第1个动作。这个地方是很违背c++常理和逻辑的,必须小心。 

结论是,不要在构造函数中使用shared_from_this;其次,如果要使用shared_ptr,则应该在所有地方均使用,不能使用D d这种方式,也决不要传递裸指针。   

另一个值得注意的地方是在类的继承树中不能有2个或更多个enable_shared_from_this<T>。例如如下代码是错误的:

1.    class A:public boost::enable_shared_from_this<A>

2.    {

3.    public:

4.        A():a(1){}

5.        virtual ~A(){}

6.        boost::shared_ptr<A>get_ptra(){return shared_from_this();}

7.        int a;

8.    };

9.    class B:public A,publicboost::enable_shared_from_this<B>

10.  {

11.  public:

12.     B():b(2){}

13.     boost::shared_ptr<B> get_ptrb()

14.     {

15.         return boost::enable_shared_from_this<B>::shared_from_this();

16.     }

17.     int b;

18.  };

19.  int _tmain(intargc, _TCHAR* argv[])

20.  {

21.     {

22.         boost::shared_ptr<B> x(new B);

23.         boost::shared_ptr<A> a1 =x->get_ptra();

24.         boost::shared_ptr<B> b1 =x->get_ptrb();

25.     }

26.     return 0;

27.  }

复制代码

意上面代码中,B同时拥有2enable_shared_from_this的基类,一个是 enable_shared_from_this<A>,另一个是enable_shared_from_this<B>。在 boost::shared_ptr<B> x(new B);这行代码中,shared_ptr<B>的构造函数仅会设置2个基类中的一个的weak_ptr。在上面的例子中,仅设置 enable_shared_from_this<A>的。如果修改B的定义为: 

class B:public boost::enable_shared_from_this<B>,publicA
 

则仅设置enable_shared_from_this<B>weak_ptr。很明显都是错误的。 

那么enable_shared_from_this以及shared_ptr为何要如此实现呢?又为什么会有如此怪异的结果呢? 

首先考察shared_ptr的构造函数:

1.    template<class Y>

2.    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y mustbe complete

3.    {

4.        boost::detail::sp_enable_shared_from_this(pn, p, p );

5.    }

6.    template<class T, class Y> voidsp_enable_shared_from_this( shared_count const & pn,boost::enable_shared_from_this<T> const * pe, Y const * px )

7.    {

8.        if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px),pn);

9.    }

复制代码

意这个sp_enable_shared_from_this是一个模板函数,而且仅调用了一次,所以不可能2 enable_shared_from_this基类的weak_ptr都被赋值。但问题在于,在调换了B的定义之后结果居然是不一样的。这里有一个很隐秘的编译器BUG。按道理来说,编译器在编译这段代码时,应该注意到无法真正决断该怎么实例化sp_enable_shared_from_this并且报一个错,但vc 2008并没有报错,而是通过编译了。(g++会在此处报错) 

那么正确的解法是怎样的呢?

1.    class B:public A

2.    {

3.    public:

4.        B():b(2){}

5.        boost::shared_ptr<B> get_ptrb()

6.        {

7.            returnboost::dynamic_pointer_cast<B>(shared_from_this());

8.        }

9.        int b;

10.  };

复制代码

意到这里B并没有直接继承enable_shared_from_this,而是使用dynamic_pointer_cast进行了类型转换。 

关于为什么enable_shared_from_this是这样实现的,可以参看作者原文: 

Every enable_shared_from_this base contains aweak_ptr, The shared_ptr constructor looks up the enable_shared_from_this baseand initializes its weak_ptr accordingly. This doesn't work when there are
two or more enable_shared_from_this bases,though. 

I could put the weak_ptr in a virtualpolymorphic base. This would force polymorphism on all clients ofenable_shared_from_this... probably acceptable. It will also force adynamic_pointer_cast in every
shared_from_this, and this may be harder toswallow, particularly in cases where RTTI is off. So I'm not sure. 

If you do want the above behavior, it's easyto duplicate, as I already responded in my first post on the topic. Just makeFooB return dynamic_pointer_cast<B>( FooA() ) and remove theenable_shared_from_this<B>
base (A needs to be made polymorphic, ofcourse). 

注意为了让dynamic_pointer_cast能工作,A必须具有虚函数,那么最简单的做法当然是令其析构函数为虚函数(通常一个class如果希望被继承,析构函数就应该为虚函数)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值