boost::shared_ptr 的 cast

boost::shared_ptr 的 cast

相信 xxx_cast 系列都很熟了。

static_cast, dynamic_cast, const_cast, reinterpret_cast.

但是当面对boost::shared_ptr的时候呢?

reinterpret_cast 可以转换任何类型,这个在讨论范围之外。

对于下面的这个定义:

 1  class  A
 2  {
 3  public :
 4       virtual   ~ A() {}
 5  };
 6 
 7  class  B
 8      :  public  A
 9  {
10  public :
11       ~ B() {}
12  };

如果用boost::shared_ptr包装的话:

1  typedef boost::shared_ptr < A >  APtr;
2  typedef boost::shared_ptr < B >  BPtr;

想想通常对指针的使用:
1  * pA  =   new  B();
2  * pB  =  dynamic_cast < B *> (pA);
3  //  unsafe
4  * upB  =  static_cast < B *> (pA);
5 
6  pA -> ;
7  pB -> ;
8  //  may crash
9  upB -> ;

如果使用boost::shared_ptr呢。
1  APtr pA  =  APtr( new  B());     //  OK
2  BPtr pB  =  pA;                //  compile error

从根本上讲,APtr 和 BPtr除了里面包装的原生指针有点关系以外,他们就是完全不同的两个类型,当然A和B也是完全不同的类型呀,可是想想看其实B是知道A的存在的。可是BPtr完全不知道APtr的存在。那这儿cast怎么进行呢?别说向下转型了,向上转型都成问题。

看看这段代码:

1 template <class T>
2 class shared_ptr
3 {
4     template <class F>
5     shared_ptr(const shared_ptr<F>& p)
6         : _p(p._p)
7         , _np(p._np)
8     {}
9  private:
10    T* _p;
11    reference_counter _np;
12 };

这个构造函数可以搞定自动向上转型,因为编译器可以自动检查 _p(p._p) 的合法性。那向下转型怎么办呢?看了上面这段代码,相信很容易解决想想啊转型的问题了。 只要把  _p(p._p)  改成 _p(dynamic_cast<T*>(p._p) 就可以了,当然要检查指针的合法性,我就不多写了。
当然boost::shared_ptr的作者已经想到这个问题,他给提供了解决方案:


 1  template < class  T,  class  U >  
 2  shared_ptr < T >  static_pointer_cast(shared_ptr < U >   const   &  r)
 3  {
 4       return  shared_ptr < T > (r, boost::detail::static_cast_tag());
 5  }
 6 
 7  template < class  T,  class  U >  
 8  shared_ptr < T >  dynamic_pointer_cast(shared_ptr < U >   const   &  r)
 9  {
10       return  shared_ptr < T > (r, boost::detail::dynamic_cast_tag());
11  }

需要用static_cast 转换普通指针的地方,用shared_static_cast 转换shared_ptr,
需要用dynamic_cast 转换普通指针的地方,用shared_dynamic_cast 转换shared_ptr.

前面说过,没有const的shared_ptr,但是有


1  const  A *  pA  =   new  B();
2  shared_ptr < const  A >  cpA(pA);          // const
3  APtr spA  =  const_pointer_cast<A>(cpA);

总结一下:
const_cast               const_pointer_cast
static_cast              static_pointer_cast
dynamic_cast             dynamic_pointer_cast

最后一个小问题:以前,boost中的shared_ptr的cast函数的名字是:shared_xxxx_cast,
后来,为了IDE自动提供帮助,改成了xxxx_pointer_cast。由此可见,设计库还是要用户至上。

你可能感兴趣的:(boost::shared_ptr 的 cast)