函式模板和類模板

2021-10-23 16:30:27 字數 4232 閱讀 3304

函式模板:template <>,<>是模板型別引數列表,<>裡面放著型別,它是由typename/class定義而來。但是我們在定義時一般不會用class來定義,因為這會使我們很容易誤認為這時乙個類模板。它是在編譯階段處理的,也就是說在編譯階段會將**展開,將typedef t替換成我們需要的型別,所以這其實是乙個型別重定義的過程

模板函式與函式模板

函式模板是乙個模板型別,而模板函式是指乙個函式。模板函式是函式模板在呼叫點例項化後生成的。讀起來有點繞口,所以用一段**來說明:

template

<

typename t>

bool

max(t a, t b)

//函式模板

intmain()

*/ max<

double

>

(10.1

,11.2);

/* bool max(double a,double b)

*/return0;

}

函式模板的實參推演

在呼叫點沒有給出型別的時候,系統會通過實參推演幫我們給出在一趟呼叫過程中

需要注意的是:

1.乙個模板型別引數只能用乙個型別來替換,即函式的二義性。

2.函式必須有實參才能推演

模板的特例化

模板的特例話分為完全特例化和部分特例化,其中函式模板只支援全特化,類模板兩種都支援。當模板的版本針對某個型別不滿足邏輯需求時,就需要針對這個型別來進行特殊的處理。例如在比較大小時,傳進兩個char*型別的引數。但是在比較時我們獲取的時字串的位址,實際上是再拿兩個位址作比較。所以針對這個型別就需要進行完全特例化。

#include

template

<

typename t>

bool

compare

(t a, t b)

template

<

>

bool compare<

const

char

*>

(const

char

* a,

const

char

* b)

bool

compare

(const

char

* a,

const

char

* b)

intmain()

那麼,在函式模板版本,函式特例化版本,普通函式版本中,它們的調動優先順序是則麼樣的呢?筆者通過上面**的實驗,最終得出了結論:普通函式版本(一級)《函式特例化版本(二級)《函式模板版本(**)

模板的型別引數

可以通過tyoename class來定義(處理機制一樣)

存在的原因:誤以為class是乙個類型別,實際上是乙個萬能型別

模板的非型別引數

<>中可以存放型別引數和非型別引數

比如:template ,但是要注意len是常量,不能是浮點型和類型別

函式的預設值

函式獲取預設值的三種方法

1.呼叫點<>直接獲取

2.實參推演

3.預設值

優先順序:呼叫點《實參推演《預設值

函式預設值的賦值規則是自右向左,模板預設值的賦值規則是隨意的。

接受不明確型別的返回值

auto rt 來定義乙個自動變數接受乙個不明確型別的返回值

auto:通過右運算元來自適應調節型別

模板的過載

普通函式版本、模板版本,和模板特例化版本都是可以共存的。

bool compare<

const

char

*>

(const

char

* a,

const

char

* b)

bool

compare

(const

char

* a,

const

char

* b)

上面的**中,特例化版本的宣告是:compare(const char*,const char*);普通函式版本的宣告是:compare(const char*,const char*).它們的形參是不同的,所以可以共存。

模板的顯示例項化

當我們把乙個函式的宣告和呼叫點寫在乙個原始檔,將函式的定義寫在另乙個原始檔中時,會編譯失敗,因為在定義點沒有去呼叫它。解決的方法:在定義點中寫入宣告即可。例如在呼叫點寫入int sum(int a,int b);這時我們在主函式去呼叫整形的sum函式時編譯通過,但是僅限於整形。當寫入其他型別時依舊會失敗。

所以我們一般會將模板的定義寫在標頭檔案中,這樣當我們需要時,直接引入標頭檔案即可。

類模板與模板類的關係和函式模板和模板函式的關係是一樣的,都需要在呼叫點將模板例項化。

#include

template

<

typename t>

class

node

/* node(int val=int())

:mdata(val),pnext(null)

*/private

: t mdata;

node

* pnext;

/* int mdata;

node* pnext;

*/};int

main()

在模板下生成的類,它裡面的私有範圍和公有範圍都是在模板中,而我們的類模板中其實主要針對的是裡面的私有變數。。所以其他函式中本來是不需要加上模板型別的,但是為了美觀來說,還是建議除了構造和析構函式以外都因該加上模板型別引數

實參推演

類模板是不支援實參推演的,必須明確的給出型別

模板的例項化

類模板的例項化是選擇性例項化,只有呼叫其中的函式時才會例項化

標題模板的型別引數列表:

1.型別引數(如:typename t)

2.非型別引數(如:int len)

3.模板引數(將乙個模板作為形參傳給另乙個模板)

類模板的拷貝建構函式的模板

假設現在生成了乙個類模板,在呼叫點例項化了乙個int型別的模板類:list c1。這時再在呼叫點例項化乙個double型別的模板類:list c2 = c1。將會報錯,這實際上是乙個拷貝建構函式,但是將int型別的模版拷貝到乙個double型別的模版中例項化顯然是不現實的。因為我們知道在類模版中拷貝建構函式(假設是乙個鍊錶類):list(list* const this,const list&rhs),這時this指標指向的是double型別,rhs指向的是int型別。

template

<

typename e>

list

(const list

& rhs)

//list(list* const this,const list&rhs)

}

類模版的特例化

特例化分為完全特例化和部分特例化。

完全特例化:在幾百個函式中如果有一兩個函式的例項化不能通過模版來正確的處理,就需要為其做乙個完全特例化版本,比如說讓兩個型別的值相加,那麼字串就沒辦法來例項化。完全特例化版本如下:

template

<

>

class

sum<

char*,

char

*>

char

*add()

private

:const

char

* ma;

const

char

* mb;

};

部分特例化:針對指標型別的偏特化:

template

<

typename t1,

typename t2>

class

sum, t2*

>

t1 add()

private

: t1* ma;

t2* mb;

};

類模板,模板類和函式模板,模板函式

單整數類 雙整數類 所以c艹跟其他強型別語言為我們提供了乙個所謂模版功能 變數型別 整數 類模板的重點是模板。表示的是乙個模板,專門用於產生類的模子。例子 1 template 2 class vector 3 使用這個vector模板就可以產生很多的class 類 vector vector ve...

函式模板 和類模板

還是例子說話。函式模板 templatemax const t a,const t b 這樣用 int int a 1,b 2 max a,b float float c 1.0f,d 2.0f max c,d double double e 1.0,f 2.0 max e,f 類模板 templa...

函式模板和類模板

1 函式模板 template 形參名,class 形參名,返回型別 函式名 引數列表 其中template和 class 是關鍵字,class 可以用typename 關見字代替,在這裡 typename 和class 沒區別,括號中的引數叫模板形參,模板形參和函式形參很相像,模板形參不能為空。一...