author:
- luixiao1223
title: Accept all compatible types
问题描述
在指针的世界你可以这么做
class Top { ... };
class Middle: public Top { ... };
class Bottom: public Middle { ... };
Top *pt1 = new Middle;
Top *pt2 = new Bottom;
const Top *pct2 = pt1;
可是在templates的世界则不可以这么做
template<typename T>
class SmartPtr {
public:
explicit SmartPtr(T *realPtr);
...;
};
SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle); // Error
SmartPtr<Top> pt2 = SmartPtr<Bottom>(new Bottom); // Error
SmartPtr<const Top> pct2 = pt1;
在模板的世界里面,SmartPtr<Middle>,SmartPtr<Top>,SmartPtr<Bottom>都是不一样的东西.他们之前没有任何关系.即便你知道Top,Middle,Bottom有继承关系.
解决方案
使用构造模板函数
template<typename T>
class SmartPtr {
public:
template<typename U> // 构造模板
SmartPtr(const SmartPtr<U>& other);
};
我们有了的思路,我们可以在里面写从一个类型到另一个类型的拷贝了.但是另外还需要解决的问题是,只允许从Bottom,Middle到Top的转换.而不允许相反的转换.这就需要另外的一项操作
template<typename T>
class SmartPtr {
public:
template<typename U>
SmartPtr(const SmartPtr<U>& other)
: heldPtr(other.get()) {} // 如果从Top 到 Buttom或Middle会发生编译报错
T* get() const { return heldPtr; }
private:
T *heldPtr;
};
编译报错正式我们实际想要 的东西.
包含copy和赋值
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);
template<class Y>
explicit shared_ptr(weak_ptr<Y> const& r);
template<class Y>
explicit shared_ptr(auto_ptr<Y>& r);
template<class Y>
shared_ptr& operator=(shared_ptr<Y> const& r);
template<class Y>
shared_ptr& operator=(auto_ptr<Y>& r);
};
如果想控制copy的方方面面,自己动手来编写copy的默认行为.
template<class T> class shared_ptr {
public:
shared_ptr(shared_ptr const& r); //copy 构造函数
template<class Y> // 泛化copy构造函数
shared_ptr(shared_ptr<Y> const& r);
shared_ptr& operator=(shared_ptr const& r); //copy assignment
template<class Y> //泛化copy assignment
shared_ptr& operator=(shared_ptr<Y> const& r);
};