c 中模板的知識梳理

2021-08-20 08:21:06 字數 3938 閱讀 2580

在c++中模板是泛型程式設計的一種體現,是採用無型別的邏輯**編寫。其作用就是達到**的復用從而減少開發人員寫重複的**。

模板分類,大的方面分為模板函式和模板類。

在時間開發過程中很有可能同一塊**,但是用了不同的型別,那麼我們就必須每個型別都要寫乙份**,為了解決這個問題,引入了模板函式。

具體是什麼樣子呢?

在模板泛型程式設計中引入乙個新的關鍵字,template關鍵字。用法如下:

template

void

function

(){}

這就是乙個模板函式。當然這只是乙個簡單的例子,我們先來解釋一下,template我們已經說過是乙個關鍵字,就是為了宣告成乙個模板函式,<>中的class是什麼,t又是什麼?class是宣告t型別的關鍵字,class也可以換成typename,而t就是下面function函式中的型別,這裡的 t 不是固定的,也可以定義成自己喜歡的,但是大多數情況下,都是定義成t帶type型別這個單詞。

模板函式的具體的格式:

template1, class 形參名2, ...> //也就是對應的型別

void 函式名(引數列表)

在使用的過程中,我們就可以像使用普通函式一樣,進行傳引數,但是必須與宣告的引數名相匹配。

怎麼理解呢?

template

void

fun(t& a, t& b){}

這個時候就不能傳參是時候傳 fun(2 , 2.2); 這樣做的會導致與模板的引數不匹配,因為我們在模板中只宣告了乙個引數型別t,而我們傳引數的時候乙個是int乙個是float型別,從而編譯器不能推演出t的型別,所以我們這時就有乙個顯示例項話。

就是在傳參的時候顯示的加上型別,如:

fun

(2, 2.2);

這裡就說明我們要傳的引數就是int型引數。在以後的我們最好使用顯示的例項化傳引數。

過載是在函式呼叫中,在同一作用域中兩個具有相同的函式名字,但是函式引數或者返回值不同的函式,

那麼在模板函式中也有過載,主要是模板函式的模板引數不同,怎麼理解?

template

void

fun(t1& a, t2& b){}

這個函式就和上面的fun在同一作用域中就形成了模板函式的過載。

這個時候顯示例項化就是

fun(1,2.2);
什麼是非型別的模板引數,非型別的模板引數就是模板引數的其中乙個為給定的引數,並且知道型別可以給乙個預設的引數(即預設引數),而且在這個值初始化後,就不然能修改。這個就有乙個好處,當我們在用靜態順序表的時候,不知到要開多大的空間,所以我們把這個可以讓呼叫者來給定來定,所以非型別的模板函式引數,當給定初始化值後就不能被改變。

例如:

template

t fun(t a)

這就是當我們呼叫的時候自己給定value的值。

fun(20); //呼叫
前面有了模板函式的鋪墊那麼我們看模板類就很相對來說比較容易。

模板類就是在實現乙個類的時候實現泛型的型別,意思就是實現的的類與型別無關,是乙個與型別無關的邏輯**。

作用也是為了進行**的復用,可以在不同的型別下用到。

我們先舉個例子來看模板類

template

class

date

;

這是就是乙個很簡單的例子,我們例項化的時候就可以

// 這裡date是乙個型別,所以必須要加上編譯器才會推演出型別

date d;

在c++中類中的成員函式可以在類外實現,所以類模板也不例外,但是在類外是實現類中的成員,有一下要注意的幾點:

1)要在實現的成員函式的前面加上template<…>

2)在類外寫成員函式時,需要加域,注意這裡的域是類加型別。

例如:我們要實現上面date的建構函式,就要寫成

template

data::date(){}

模板引數是什麼?模板引數就是把乙個模板類的引數定義成了另乙個模板類。

例如:我們在實現順序表的時候,用乙個模板類,實現好了以後,又需要實現乙個棧的資料結構,那麼我們可以利用順序表的資料結構,實現乙個容器介面卡,也就是把順序表當乙個型別,然後為棧模板類的引數。

如:

template

class stack

;

這樣我們要怎麼例項化呢?

stack > s; //在類中t 現在給定的型別就是int
在上面的t 和seqlist< t >是一種型別。

但是在用的時候如果不注意把傳引數的兩個寫成不一樣的結果就顯然不正確了。

模板的模板引數就是為了解決上面的問題,但是也帶來問題,導致模板類的可讀性降低。

我們就在上面的**上做出簡單的改進

// 與上面相比後面的沒有了t

template

class container = seqlist >

class stack

;

這個例項化就是

stack s; // 只寫出容器適配的類名字,不寫t
在函式模板中有非型別的函式模板引數,現在是在類中,但是用法和原理大同小異,沒有什麼特別大的區別。

模板的特化就是在類的模板的基礎上加上,給不同的型別進行一些特殊的處理**,怎麼理解?

就是我們產生模板類就是為了能達到**的復用,但是在不同的型別中,我們為了提高效率,有些類的型別用一種更高效的方法實現,這樣就可以提高效率,所以我們就用模板類的特化來實現。

那麼模板的特化怎麼實現的呢?就是在模板類為原生模板的基礎上實現特化。

模板類中又分為全特化和偏特化(區域性特化)

模板類中全特化舉例子:

template

class

date

;

全特化

template<>

class date // 在這裡加上特化後的型別

public:

date();

~date();

private:

int year; // 這裡也就直接用特化的型別

int month;

int day;

};

特化後在類外寫成員函式就不需要寫模板引數。

我們來模擬一下全特化,區域性特化從表面意思上就可以知道,在多個模板引數的時候,我們可以特化其中乙個引數,這就是區域性特化。

我們就拿上面的例子來講

template

class

date

;

偏特化

templateclass dateint> // 在這裡加上特化後的型別

public:

date();

~date();

private:

int year; // 這裡也就直接用特化的型別

t1 month;

t1 day;

};

最後還有一點要注意就是在模板中,如果沒有進行呼叫,編譯器不會對其進行語法檢查,如果有呼叫,那麼編譯器才會根據型別進行生成乙份**。

還有就是要在編寫模板的時候,不能把定義與宣告放在兩個不同的檔案中,這樣編譯器會在編譯完成後,在鏈結過程中會產生鏈結錯誤。

在模板類的特化中,如果在呼叫的型別是模板類特化的,那麼就會直接去特化的類,編譯器不會再生成乙份**。順序是有全特化找全特化,沒有看區域性特化,沒有才去生成乙份模板類的**。

如有錯誤,還望指正,謝謝!

C語言基礎知識梳理

準備開乙個部落格專欄,關於cocos2d x遊戲開發的。因為cocos2d x是c 編寫的,所以也打算使用c 來講。1 基本型別 1.1 數值型別 a 整型 短整型short,整型int,長整型long b 浮點型 單精度float,雙精度double 1.2 字元型別char 2 構造型別 2.1...

c 基本知識梳理(1)

1 c 和標準c 包含完整系統類庫是標準c 在97年完善,90年代初,帶有語言標準,不含有標準類庫,而且各種功能在不同種逐漸推出。vc 和g 以及其他的c 編譯器必須符合語言標準。無論vc 公升級到什麼版本,語言標準不一定公升級。2 標準類庫主要包含 string list vector map只要...

C語言基礎知識梳理

資料型別 常量 常量包括字面常量 直接常量和符號常量 變數 c語言規定標誌符只能由字母 數字和下劃線三種字元組成,且第乙個字元必須是字母或者下劃線 必須壓迫先定義後使用 每乙個變數被定義以確定型別後,在編譯時就能為其分配相應的儲存單元 整數型別 整數常量有十進位制 八進位制和十六進製制 d 整形變數...