- 了解隱式接口和編譯期多態
- 編譯期多態和運行期多態
- 運行期多態就好比是virtual函數再運行的時候才確定該virtual函數該被綁定為哪個函數,運行的時候才確定函數類型。
- 編譯期多態就好比是泛型編程和模板編程中,在編譯的時候才確定哪個函數該被調用,根據函數的類型去確定。
- 顯示接口和隱式接口
- 顯示接口由函數的簽名式構成
class widget{ public:widget();virtual ~widget();virtual std::size_t size() const;virtual void normalize();void swap(widget& other); }; //這個其中:上述的這些函數都構成了這個public的顯示接口
- 隱式接口:由一組表達式組成;if (w.size()>10 && w!=somenastywidget)...
- 顯示接口由函數的簽名式構成
- classes和templates都支持接口和多態;對classes而言接口是顯示的,一以函數簽名為中心。多態是通過virtual函數發生在運行期;對template參數而言,接口是隱式的,基于有效表達式。多態則是通過template具現化和函數重載解析發生于編譯期。
- 編譯期多態和運行期多態
- typename的意義
- 在template聲明式中,class和typename沒有什么不同。
template <class T> class widget; template <typename T>class widget;
- 從屬名稱和謂非從屬名稱
- 從屬名稱(dependent typename):表示這個變量名稱是依賴于template參數的,有模板參數確定的。
- 利用這個從屬名稱可能有時候會發生名稱晦澀難懂,或者是名稱過長導致名稱無法解析。這個時候我們可以使用typename關鍵字,可以讓編譯器知道某個長名稱是一個參數類型,這樣可以消除歧義。
- 一般我們在template中指涉了一個從屬類型名稱,就要在它前面添加關鍵字typename。
- 特殊:typename不可以出現在base classes list內的從屬類型名稱之前,也不可在member initialization list中作為base class修飾符。
- 謂非從屬名稱(non-dependent typename):這個變量是不依賴與template參數的,是一個正常的變量名稱。
- 從屬名稱(dependent typename):表示這個變量名稱是依賴于template參數的,有模板參數確定的。
- typedef:作用是用一個簡短的名稱替換一個較長的名稱
typedef typename std::iterator_traits<itrat>::value_type value_type; //在這里 typename是指定從屬名稱,typedef是讓這個長的從屬名稱變為短的value_type。
- 在template聲明式中,class和typename沒有什么不同。
- 學會處理模板化基類內的名稱
- 可以在派生類模板中內通過this->指涉base class templates內的成員名稱,或者籍由一個明白寫出的base class資格修飾符完成
- 可以在派生類模板中內通過this->指涉base class templates內的成員名稱,或者籍由一個明白寫出的base class資格修飾符完成
- 將于參數無關的代碼抽離templates
- templates生成多個classes和多個函數,所以任何template代碼都不該與某個造成膨脹的template參數產生相依關系。
- 因非類型末班參數而造成的代碼膨脹往往可以消除,做法是以函數參數或class成員變量替換template參數。
- 因類型參數而造成的代碼膨脹往往可以降低,做法是讓帶有相同二進制表述的具現類型共享實現碼。
- 運用成員函數模板接收所有兼容類型
- 成員模板函數
template <typename T> class smartptr{ public:template<typename U>smartptr(const smartptr<U> &other);//成員模板函數 };
- 請使用成員模板函數生成可以收所有兼容類型的函數;如果你聲明成員模板函數用于泛化copy構造函數和泛化assignment操作,你還是需要聲明正常的copy構造函數和泛化assignment操作
- 成員模板函數
?