好比有一個Base類和一個Derived類,像下面這樣:函數
1 class BaseClass 2 {…}; 3 4 class DerivedClass : public BaseClass 5 {…};
由於是父類與子類的關係,因此能夠這樣寫:spa
1 DerivedClass *d; 2 BaseClass *b = static_cast< BaseClass *>d; // 用C風格直接是 b = (BaseClass*) d;
咱們能夠弄一個簡易的Shared型智能指針類,若是直接像下面這樣寫:指針
1 template <class T> 2 class SharedPtr 3 { 4 private: 5 T* Ptr; 6 static size_t Count; 7 8 public: 9 SharedPtr(T* _ptr) 10 { 11 Count = 1; 12 Ptr = _ptr; 13 cout << "Constructor Called Same" << endl; 14 } 15 ~SharedPtr() 16 { 17 cout << "Destructor Called" << endl; 18 if (--Count == 0) 19 { 20 cout << "Delete Pointer" << endl; 21 delete Ptr; 22 Ptr = NULL; 23 } 24 } 25 26 SharedPtr(const SharedPtr<T>& _Smart) 27 { 28 cout << "Copy Constructor Called Same" << endl; 29 Ptr = _Smart.Ptr; 30 ++Count; 31 } 32 };
那麼顯示編譯器不會容許SharedPtr<BaseClass> pb(pd),由於在編譯期替換T時,拷貝構造函數明確了接受類型必須是SharedPtr<BaseClass>,而由SharedPtr<DerivedClass>對象至SharedPtr<BaseClass>的轉換並不存在,因此編譯器報錯。code
爲了能使這樣的轉換合法,咱們須要在原來的基礎上這樣寫:對象
1 class SharedPtr 2 { 3 private: 4 T* Ptr; 5 static size_t Count; 6 7 public: 8 SharedPtr(T* _ptr) 9 { 10 Count = 1; 11 Ptr = _ptr; 12 cout << "Constructor Called Same" << endl; 13 } 14 15 template <class Other> 16 SharedPtr(Other* _ptr) 17 { 18 Count = 1; 19 Ptr = static_cast<T*> (_ptr); 20 cout << "Constructor Called Other" << endl; 21 } 22 23 ~SharedPtr() 24 { 25 cout << "Destructor Called" << endl; 26 if (--Count == 0) 27 { 28 cout << "Delete Pointer" << endl; 29 delete Ptr; 30 Ptr = NULL; 31 } 32 } 33 34 T* GetPointer() 35 { 36 return Ptr; 37 } 38 39 T* GetPointer() const 40 { 41 return Ptr; 42 } 43 44 SharedPtr(const SharedPtr<T>& _Smart) 45 { 46 cout << "Copy Constructor Called Same" << endl; 47 Ptr = _Smart.Ptr; 48 ++Count; 49 } 50 51 52 template <class Other> 53 SharedPtr(const SharedPtr<Other>& _Smart) 54 { 55 cout << "Copy Constructor Called Other" << endl; 56 Ptr = static_cast<T*>(_Smart.GetPointer()); 57 ++Count; 58 } 59 };
注意代碼標註爲藍色的部分(即爲泛化部分),這裏另外聲明瞭一個模板參數Other,它能夠與T相同,也能夠不一樣,也就意味着它能夠接受任何能夠轉化成T的類型了,好比父子類。這裏還定義了GetPointer的方法,由於拷貝構建中傳入的對象不必定是屬於同一個類的,因此不能保證能夠訪問到類的私有成員。Ptr = static_cast<T*>(_Smart.GetPointer())這句話其實就是轉換的實質了,只要任何能夠轉成T*的Other*,都是能夠經過編譯的,但若是是風馬牛不相及的兩個類,就不會經過編譯。這裏有一點要強調一下,咱們能夠把double轉成int(窄化),也能夠把int轉成double(寬化),但注意double*與int*之間是不能相互轉的,若是這樣寫int *a = (int*) (new double(2)),是不能經過編譯的,能夠用static_cast轉換的類要有繼承關係。代碼還有賦值運算符也須要提供一個非泛化的版本和泛化的版本,這裏簡略沒有寫出。blog
這裏還有一個須要注意的地方,在class類聲明泛化copy構造函數(member template),並不會阻止編譯器生成它們本身的copy構造函數(non-template),換言之,若是程序中只寫了泛化的copy構造函數,那麼編譯器仍是會自動生成一個非泛化的版本出來,若是不想要這個缺省版本,那必定不能偷懶,要兩個版本的copy構造函數都要寫。繼承
最後總結一下:ci
1. 請使用member function templates(成員函數模板)生成「可接受全部兼容類型」的函數;element
2. 若是你聲明member templates用於「泛化copy構造」或「泛化assignment操做」,你仍是須要聲明正常的copy構造函數和copy assignment操做符。get
下面附上微軟對shared_ptr類的聲明,對比黃色加亮部分,能夠看到本條款所說的技術要點。
1 template<class Ty> 2 class shared_ptr { 3 public: 4 typedef Ty element_type; 5 6 shared_ptr(); 7 shared_ptr(nullptr_t); 8 shared_ptr(const shared_ptr& sp); 9 shared_ptr(shared_ptr&& sp); 10 template<class Other> 11 explicit shared_ptr(Other * ptr); 12 template<class Other, class D> 13 shared_ptr(Other * ptr, D dtor); 14 template<class D> 15 shared_ptr(nullptr_t, D dtor); 16 template<class Other, class D, class A> 17 shared_ptr(Other *ptr, D dtor, A alloc); 18 template<class D, class A> 19 shared_ptr(nullptr_t, D dtor, A alloc); 20 template<class Other> 21 shared_ptr(const shared_ptr<Other>& sp); 22 template<class Other> 23 shared_ptr(const shared_ptr<Other>&& sp); 24 template<class Other> 25 explicit shared_ptr(const weak_ptr<Other>& wp); 26 template<class Other> 27 shared_ptr(auto_ptr<Other>& ap); 28 template<class Other, class D> 29 shared_ptr(unique_ptr<Other, D>&& up); 30 template<class Other> 31 shared_ptr(const shared_ptr<Other>& sp, Ty *ptr); 32 ~shared_ptr(); 33 shared_ptr& operator=(const shared_ptr& sp); 34 template<class Other> 35 shared_ptr& operator=(const shared_ptr<Other>& sp); 36 shared_ptr& operator=(shared_ptr&& sp); 37 template<class Other> 38 shared_ptr& operator=(shared_ptr<Other>&& sp); 39 template<class Other> 40 shared_ptr& operator=(auto_ptr< Other >&& ap); 41 template <class Other, class D> 42 shared_ptr& operator=(const unique_ptr< Other, D>& up) = delete; 43 template <class Other, class D> 44 shared_ptr& operator=(unique_ptr<Other, D>&& up); 45 void swap(shared_ptr& sp); 46 void reset(); 47 template<class Other> 48 void reset(Other *ptr); 49 template<class Other, class D> 50 void reset(Other *ptr, D dtor); 51 template<class Other, class D, class A> 52 void reset(Other *ptr, D dtor, A alloc); 53 Ty *get() const; 54 Ty& operator*() const; 55 Ty *operator->() const; 56 long use_count() const; 57 bool unique() const; 58 operator bool() const; 59 60 template<class Other> 61 bool owner_before(shared_ptr<Other> const& ptr) const; 62 template<class Other> 63 bool owner_before(weak_ptr<Other> const& ptr) const; 64 template<class D, class Ty> 65 D* get_deleter(shared_ptr<Ty> const& ptr); 66 };