条款45:运用成员函数模板接受所有兼容类型(Use member function templates to accept “all compatible types“)

条款45:运用成员函数模板接受所有兼容类型

与智能指针相比,普通内置指针的一大优点是支持隐式转换。

class Top { ... };
class Middle : public Top { ... };
class Bottom : public Middle { ... };
Top* pt1 = new Middle; //  Middle* 转换为 Top*
Top* pt2 = new Bottom; //  Bottom* 转换为 Top*
const Top* pct2 = pt1; //  Top*  const Top*

在智能指针类中模拟这种转换就很棘手。

template<typename T>
class SmartPtr {
public:  
    explicit SmartPtr(T* realPtr); // 智能指针通常由内置指针初始化
    ...
};
//同一个模板的不同实例之间没有内在的联系,因此编译器将SmartPtr<Middle>和SmartPtr<Top>视为完全不同的类
// SmartPtr<Middle> 转换为 SmartPtr<Top>
SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle); 
// SmartPtr<Bottom> 转换为 SmartPtr<Top>
SmartPtr<Top> pt2 = SmartPtr<Bottom>(new Bottom); 
// SmartPtr<Top> 转换为 SmartPtr<const Top>
SmartPtr<const Top> pct2 = pt1;  

通过构造函数模板,更好的体现对象间的继承关系:

template<typename T>
class SmartPtr {
public:
    template<typename U> // “构造函数”模板,成员函数模板
    //SmartPtr<T>可以从SmartPtr<U>创建
    SmartPtr(const SmartPtr<U>& other); // 注意:是non-explicit 
    ...  
};

我们还需要控制转换的方向:

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; // SmartPtr持有的内置指针
};

成员函数模板的用途不仅限于构造函数。

template<class T> class shared_ptr {
public:
    template<class Y>
    explicit shared_ptr(Y* p); // 构造函数,支持任何兼容的内置指针
    template<class Y> 
    shared_ptr(shared_ptr<Y> const& r); // 或shared_ptr
    template<class Y> 
    explicit shared_ptr(weak_ptr<Y> const& r); // 或weak_ptr
    template<class Y>
    explicit shared_ptr(auto_ptr<Y>& r); // 或unique_ptr
    template<class Y>  
    shared_ptr& operator=(shared_ptr<Y> const& r);   //赋值
    template<class Y>  
    shared_ptr& operator=(auto_ptr<Y>& r);  
    ...
};

声明泛化的拷贝构造函数(成员模板)不会阻止编译器生成自己的拷贝构造函数(非模板),想控制拷贝构造的方方面面,必须同时声明泛化和“普通”版本的拷贝构造函数。赋值也一样。

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); // 泛化的拷贝赋值
    ...
};

总结

  1. 使用成员函数模板生成接受所有兼容类型的函数。
  2. 如果为泛化的拷贝构造函数或赋值运算符声明成员模板,还需要正常声明普通的版本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值