智能指针是行为类似指针但增加了额外功能的对象,真正的指针支持隐式转换,如派生类指针到基类指针、非常量指针到常量指针的转换。在用户定义的智能指针类中模仿这些转换需要使用成员函数模板(成员模板)。
1. 成员函数模板用于支持类型转换
在同一个模板的不同实例化之间没有继承关系,为了实现智能指针类之间的转换,需要编写构造函数模板(成员函数模板),即泛型化拷贝构造函数。
#include <iostream>
// 定义继承体系
class Top { public: virtual ~Top() {} };
class Middle : public Top {};
class Bottom : public Middle {};
// 自定义智能指针类
template<typename T>
class SmartPtr {
public:
// 普通构造函数
explicit SmartPtr(T* realPtr) : heldPtr(realPtr) {}
// 泛型化拷贝构造函数
template<typename U>
SmartPtr(const SmartPtr<U>& other) : heldPtr(other.get()) {
// 这里只有当存在从 U* 到 T* 的隐式转换时才能编译
}
// 获取内部指针
T* get() const { return heldPtr; }
private:
T* heldPtr;
};
int main() {
SmartPtr<Middle> spMiddle(new Middle);
SmartPtr<Top> spTop = spMiddle; // 调用泛型化拷贝构造函数
std::cout << "spTop's internal pointer: " << spTop.get() << std::endl;
return 0;
}
在上述代码中,SmartPtr
类有一个泛型化拷贝构造函数,它允许从一个 SmartPtr<U>
创建一个 SmartPtr<T>
,前提是存在从 U*
到 T*
的隐式转换。
2. 过滤成员函数模板生成的函数
泛型化拷贝构造函数可能提供了比我们想要的更多的功能,需要通过构造函数模板的实现将转换限定在我们想要的范围。
template<typename T>
class SmartPtr {
public:
template<typename U>
SmartPtr(const SmartPtr<U>& other) : heldPtr(other.get()) {
// 只有当存在从 U* 到 T* 的隐式转换时才能编译
}
T* get() const { return heldPtr; }
private:
T* heldPtr;
};
3. 成员函数模板用于支持赋值操作
成员函数模板的用途不限于构造函数,还可用于支持赋值操作。例如,tr1::shared_ptr
支持从所有兼容的内置指针、tr1::shared_ptr
、auto_ptr
和 tr1::weak_ptr
构造,以及从除 tr1::weak_ptr
以外的这些类型赋值。
#include <memory>
template<class T>
class shared_ptr {
public:
// 从任何兼容的内置指针构造
template<class Y>
explicit shared_ptr(Y* p);
// 从 shared_ptr 构造
template<class Y>
shared_ptr(shared_ptr<Y> const& r);
// 从 weak_ptr 构造
template<class Y>
explicit shared_ptr(weak_ptr<Y> const& r);
// 从 auto_ptr 构造
template<class Y>
explicit shared_ptr(auto_ptr<Y>& r);
// 从 shared_ptr 赋值
template<class Y>
shared_ptr& operator=(shared_ptr<Y> const& r);
// 从 auto_ptr 赋值
template<class Y>
shared_ptr& operator=(auto_ptr<Y>& r);
};
4. 成员函数模板不改变语言基本规则
声明泛型化拷贝构造函数或泛型化赋值操作符的成员模板不会阻止编译器生成默认的拷贝构造函数和拷贝赋值运算符。因此,如果要全面控制拷贝构造和赋值操作,必须同时声明泛型化和常规的拷贝构造函数与拷贝赋值运算符。
#include <memory>
template<class T>
class shared_ptr {
public:
// 常规拷贝构造函数
shared_ptr(shared_ptr const& r);
// 泛型化拷贝构造函数
template<class Y>
shared_ptr(shared_ptr<Y> const& r);
// 常规拷贝赋值运算符
shared_ptr& operator=(shared_ptr const& r);
// 泛型化拷贝赋值运算符
template<class Y>
shared_ptr& operator=(shared_ptr<Y> const& r);
};
总结要点
- 使用成员函数模板生成接受所有兼容类型的函数,以实现智能指针类之间的类型转换和赋值操作。
- 若为泛型化拷贝构造或泛型化赋值声明了成员模板,仍需声明常规拷贝构造函数和拷贝赋值运算符,以全面控制拷贝构造和赋值行为。