由於使用模板可使程序員創建具備通用類型的函數庫和類庫。模板也是C++語言支持參數化多態性的工具。程序員
函數模板編程
函數模板能以一樣的程序代碼對不一樣類型的數據進行處理,其關鍵是將所處理的數據類型說明爲參數,即類型參數化。數組
定義函數模板的通常形式是:函數
template <class 類型參數名1 ,class 類型參數名 2,…>
函數返回值類型 函數名(形參表)
{
函數體
}工具
說明:spa
(1)這裏的類型參數名就是表明形形色色數據類型的通用參數名,它能夠表明基本數據類型,也能夠表明類。指針
(2)編寫函數模板的方法是:code
step 1:定義一個普通的函數,數據類型採用具體的普通的數據類型,仍以打印數組爲例,先定義一個打印整型數組的普通函數:對象
void printArray(int *array,int count)編譯
{
for (int i=0;i<count;i++)
cout<<array[i]<<" ";
cout <<endl;
}
step 2:將數據類型參數化:將其中具體的數據類型名(如 int )所有替換成由本身定義的抽象的類型參數名(如T)。
step 3:在函數頭前用關鍵字template引出對類型參數名的聲明。這樣就把一個具體的函數改形成一個通用的函數模板:
template <class T> void printArray(T *array,int count)
{
for (int i=0;i<count;i++)
cout<<array[i]<<" ";
}
(3)函數模板不是一個能夠執行的函數,它只是對函數功能的程序描述,編譯程序不爲它生成執行代碼。
(4)當編譯程序遇到函數調用:
函數名 (實參表)時,自動將實參表中具體的數據類型替換函數模板中的類型參數,生成一個隱含的重載函數,該重載函數 的程序代碼與函數模板相同,類型則採用實參表中的具體數據類型。仍之前面所建立的打印數組函數模板爲例,當程序出現函數調用語句 printArray(a,aCount);時,編譯程序將根據第一個實參a的數據類型int 匹配類型參數T,將函數模板中的全部T都替換成具體的數據 類型int,從而產生一個具體的可執行函數的定義(這個過程稱爲模板實例化):
void printArray(int *array,int count);
模板函數
函數模板是對一組函數的描述,它不是一個實實在在的函數,編譯系統並不產生任何執行代碼。當編譯系統在程序中發現有與函數模板中相匹配的函數調用時,便生成一個重載函數,該重載函的函數體與函數模板的函數體相同。該重載函數稱爲模板函數。
類模板
類模板概念的由來:列舉一個鏈表類來討論類模板引進的必要性。下面有一個List類是鏈表類,嵌套了一個Node結構類型。具體定義以下:
class List { //定義鏈表類 public: List(); //聲明構造函數 void Add(int&); //聲明增長節點的成員函數 void Remove(int&); //聲明刪除節點的成員函數 int* Find(int&); //聲明查找節點的成員函數 void PrintList(); //聲明打印鏈表的成員函數 ~List(); //聲明析構函數 protected: struct Node { //定義結點的結構類型 Node *pNext; //指向下一個結點的指針成員 int* pT; //指向本結點數據的指針成員 } };
該鏈表結點的數據類型是int型,若是要使鏈表中結點的數據是其它類型(如char型、double型),就要從新定義鏈表類,因爲這些類僅僅只是 結點的數據類型不一樣,其他代碼徹底相同,所以形成程序代碼大量重複。爲鏈表類家族建立一個通用鏈表類模板就能最大限度地減小程序代碼的冗餘,爲此引進類模 板。將上述的List類中的數據類型用一個通用參數T來代替,以下所示:
template<class T> class List { //定義通用鏈表類模板 public: List(); //聲明構造函數 void Add(T&); //聲明增長節點的成員函數 void Remove(T&); //聲明刪除節點的成員函數 T* Find(T&); //聲明查找節點的成員函數 void PrintList(); //聲明打印鏈表的成員函數 ~List(); //聲明析構函數 protected: struct Node{ //定義結點的結構類型 Node *pNext; //指向下一個結點的指針成員 T* pT; //指向本結點數據的指針成員 }; };
這個類模板中使用了參數類型T,它被用在成員函數Add()、Remove()和Find()的說明中以及結構體的定義中。實際上,一個類模板是描述了一組類。可見,引進類模板也一樣是爲了減小程序員的重複勞動,克服程序冗餘的一種方法。
如同函數模板同樣,使用類模板使用戶能夠爲類定義一種模式,使得類中的某些數據成員、某些成員函數的參數、某些成員函數的返回值能取任意類型。 類模板是對一批僅僅成員數據類型不一樣的類的抽象,程序員只要爲這一批類所組成的整個類家族建立一個類模板,給出一套程序代碼,就能夠用來生成多種具體的 類,(這類能夠看做是類模板的實例),從而大大提升編程的效率。
定義類模板的通常形式是:
template <類型名 參數名1,類型名 參數名2,…> class 類名 { 類聲明體 }; 例如, template <class T> class Smemory { … public: void mput(T x); … }
表示定義一個名爲Smemory的類模板,其中帶類型參數T。
在類模板的外部定義類成員函數的通常形式是:
template <類型名 參數名1,類型名 參數名2,…> 函數返回值類型 類名<參數名 1 參數名 2,…>::成員函數名(形參表) { 函數體 } 例如: template <class T> void Smemory<T>::mput(T x) {…}
表示定義一個類模板Smemory的成員函數,函數名爲mput,形參x的類型是T,函數無返回值。
類模板是一個類家族的抽象,它只是對類的描述,編譯程序不爲類模板(包括成員函數定義)建立程序代碼,可是經過對類模板的實例化能夠生成一個具體的類以及該具體類的對象。
與函數模板不一樣的是:函數模板的實例化是由編譯程序在處理函數調用時自動完成的,而類模板的實例化必須由程序員在程序中顯式地指定,
其實例化的通常形式是:
類名 <數據類型 1(或數據),數據類型 2(或數據)…> 對象名
例如,Smemory<int> mol;表示將類模板Smemory的類型參數T所有替換成int 型,從而建立一個具體的類,並生成該具體類的一個對象mol。