C++箴言:用成员函数模板接受兼容类型(二)

2014-11-24 13:16:36 · 作者: · 浏览: 19
r functions(成员函数)的群体。

  假如 SmartPtr 跟随 auto_ptr 和 tr1::shared_ptr 的脚步,提供一个返回被这个 smart pointer(智能指针)持有的 built-in pointer(内建指针)的拷贝的 get member function(get 成员函数)(参见《 C++箴言:在资源管理类中准备访问裸资源 》),我们可以用 constructor template(构造函数模板)的实现将转换限定在我们想要的范围:

template
class SmartPtr {
 public:
  template
  SmartPtr(const SmartPtr & other) // initialize this held ptr
  : heldPtr(other.get()) { ... } // with others held ptr

  T* get() const { return heldPtr; }
  ...

 private: // built-in pointer held
  T *heldPtr; // by the SmartPtr
};

  我们通过 member initialization list(成员初始化列表),用 SmartPtr 持有的类型为 U* 的指针初始化 SmartPtr 的类型为 T* 的 data member(数据成员)。这只有在“存在一个从一个 U* 指针到一个 T* 指针的 implicit conversion(隐式转换)”的条件下才能编译,而这正是我们想要的。最终的效果就是 SmartPtr 现在有一个 generalized copy constructor(泛型化拷贝构造函数),它只有在传入一个 compatible type(兼容类型)的参数时才能编译。

  member function templates(成员函数模板)的用途并不限于 constructors(构造函数)。它们的另一个常见的任务是用于支持 assignment(赋值)。例如,TR1 的 shared_ptr(再次参见《 C++箴言:使用对象管理资源 》)支持从所有兼容的 built-in pointers(内建指针),tr1::shared_ptrs,auto_ptrs 和 tr1::weak_ptrs构造,以及从除 tr1::weak_ptrs 以外所有这些赋值。这里是从 TR1 规范中摘录出来的一段关于 tr1::shared_ptr 的内容,包括它在声明 template parameters(模板参数)时使用 class 而不是 typename 的偏好。(就像《 C++箴言:理解typename的两个含义 》中阐述的,在这里的上下文环境中,它们的含义严格一致。)

template class shared_ptr {
public:
 template // construct from
 explicit shared_ptr(Y * p); // any compatible
 template // built-in pointer,
 shared_ptr(shared_ptr const& r); // shared_ptr,
 template // weak_ptr, or
 explicit shared_ptr(weak_ptr const& r); // auto_ptr
 template
 explicit shared_ptr(auto_ptr & r);
 template // assign from
 shared_ptr& operator=(shared_ptr const& r); // any compatible
 template // shared_ptr or
 shared_ptr& operator=(auto_ptr & r); // auto_ptr
 ...
};

  除了 generalized copy constructor(泛型化拷贝构造函数),所有这些 constructors(构造函数)都是 explicit(显式)的。这就意味着从 shared_ptr 的一种类型到另一种的 implicit conversion(隐式转换)是被允许的,但是从一个 built-in pointer(内建指针)或其 smart pointer type(智能指针类型)的 implicit conversion(隐式转换)是不被许可的。(explicit conversion(显式转换)――例如,经由一个 cast(强制转型)――还是可以的。)同样引起注意的是 auto_ptrs 被传送给 tr1::shared_ptr 的 constructors(构造函数)和 assignment operators(