模板與泛型程式設計

2021-08-09 09:20:28 字數 3190 閱讀 6198

模板是泛型變成的基礎。泛型程式設計:編譯與型別無關的**,是一種復用的方式,模板分為模板函式和模板類。

模板函式是乙個通用的函式模板,而不是為每一種型別定義乙個新函式,乙個函式模板就像乙個公式,針對不同型別函式生成不同的函式版本。

關鍵字:template

以 template 開始,後面跟乙個模板引數列表(乙個逗號分隔的乙個或多個模板引數的列表)。

templatet>

t add(const t &a1,const t &a2)

注意:

在模板定義中,模板引數列表不能為空。

每乙個模板引數前面必須加上class或typename。

模板函式也能定義為inline函式,inline關鍵字必須放在模板形參表之後,返回值之前。

templatet>

inline int add(const t&a1,const t&a2)

注意:

當編譯器遇到乙個模板定義時,他並不生成**,只有當我們例項化出模板的乙個特定版本時,編譯器才會生成**。

當我們呼叫乙個函式模板時,編譯器通常會用函式實參類推斷出模板實參,使用實參的型別來繫結到模板型別t的型別。

template

t add(const t &a1,const t &a2)

void test()

這種方式叫做隱式例項化,中間過程不涉及型別轉換。

顯示例項化:

template

int add(const t &a1,const t &a2)

void test()

首先由編譯器推斷出實參型別應該是char,但是因為此時將模板函式顯示例項化為int,會將char型別轉換為int型別,隨之生成的函式也會是int型別,在顯示例項化中可能會涉及到型別轉換。

編譯器執行的轉換:

const 轉換:接收const引用或者const指標的函式可以分別用非const物件的引用或者指標來呼叫。

陣列或函式到指標的轉換:如果模板形參不是引用型別,則對陣列或函式型別的實參應用常規指標轉換。陣列實參將當做指向其第乙個元素的指標,函式實參當做指向函式型別的指標。

上面的add()函式有乙個模板型別引數,我們可以將型別模板引數像內建型別或類型別說明符一樣使用。型別引數也可以用來指定返回型別,以及在函式體內用於變數宣告或型別轉換。

templatet>

t foo(t *p)

除了定義型別引數,還可以在模板中定義非型別模板引數,乙個非型別模板引數表示乙個值而非乙個型別。通過乙個特定的型別名而非關鍵字來指定非型別模板引數。

非型別模板引數可以是乙個整型,或者是乙個指向物件或函式型別的指標或者引用。

例:

template

int compare(const

char (&p1)[m],const

char (&p2)[n])

void test()

編譯器會使用字面常量的大小來代替m和n,從而例項化模板。

int compare(const char(&p1)[3],const char (&p2)[4])

模板形參名字只能在模板形參之後到模板宣告或定義的末尾之間使用.

typedef

int t;

tmplate

void fun(t t)

template

//

t max(const t& left, const t& right)

template

//

t max(const t& a, const t& b, const t& c)

; int main()

從這個例子可以看出,在同乙個程式內,非模板函式可以和模板函式同時存在,可以將非模板函式看做時函式模板已經例項化出的乙個函式。

非模板函式和同名函式模板,如果其他條件都相同,在調動時會優先調動非模板函式而不會從該模板產生出乙個例項。如果模板可以產生乙個具有更好匹配的函式, 那麼將選擇模板。

如果在條件相同的情況下,要呼叫模板來匹配呼叫,則必須顯示的給出乙個空模板實參列表。

當函式模板需要對某些型別進行特化處理,稱為函式模板的特化。

這裡給出乙個compaer模板函式。

template

int compare(const t left, const t right)

void test()

此時希望輸出乙個 -1,但是實際缺輸出了乙個 1 。因為在函式呼叫過程中,直接將兩個字串的位址傳給模板函式,此時比較的只是兩個字串位址的大小,而不是對內容進行比較。

此時就需要對模板進行特化

tempalte

int compare(const t left, const t right)

template

<> //特化 空尖括號

int comparechar*>(const

char* left, const

char* right)

//函式名後接模板名和一對尖括號,尖括號中指定這個特化的模板形參

注意:

特化的宣告必須與特定的模板相匹配,主要分析const到底是頂層const還是底層const。

模板類是用來生成類的藍圖。編譯器不能為類模板推斷模板引數型別。

模板類同樣以關鍵字template開始,後面跟模板引數列表,在模板類的定義重,我們將模板引數代替使用模板時使用者需要提供的型別或值。

template

class struct

;struct s1; //顯示模板引數

模板引數遵循普通的作用域規則,乙個模板引數名的可用範圍是其生命之後,至模板宣告或定義結束之前。同樣遵守名字遮蔽規則。

注:在模板內不能重用模板引數名

預設模板實參:

template t,typename f = less>

int compare(const t &t1,const t &t2,f f=f())

//compare有乙個預設模板實參less,和乙個預設函式實參f()

模板與泛型程式設計

泛型程式設計 編寫與型別無關的通用 是 復用的一種手段。模板是泛型程式設計的基礎。函式模板代表了乙個函式家族,該函式模板與型別無關,在使用時被引數化,根據實參型別產生函式的特定型別版本。模板的格式 template 返回值型別 函式名 引數列表 模板分為類模板和函式模板 模板它本身並不是函式,是編譯...

模板與泛型程式設計

一 函式模板 模板定義以關鍵字template開始,後跟乙個模板引數列表,在模板定義中,模板引數列表不能為空。模板型別引數 型別引數前必須使用class或typename關鍵字。非型別模板引數 表示乙個值而不是乙個型別 陣列引用形參 arr兩端的括號必不可少 void print int arr 1...

7 模板與泛型程式設計

understanding implicit inte ces and compile time polymorphism.編譯期多型 模板根據型別例項化 過載函式。執行期多型 執行時決定那個乙個virtual函式被呼叫。understand the two meanings of typename...