函式模板基礎

2021-09-25 21:13:05 字數 4206 閱讀 4692

本章知識點:(不按順序講解)

模板的型別引數

模板的非型別引數

模板的實參推演

模板函式的過載

以上為本文講解的內容
模板的特例化(專用化)

模板的例項化:顯式例項化 和 隱式例項化

1.模板的型別引數:

定義模板引數列表:

template //型別由typename或者class指定;

t 和 e是型別引數,將來專門接收各種各樣的型別.

2.函式模板與模板函式:

2.1 函式模板:即函式的模板;

//這是乙個函式模板

template bool compare(t a,t b)

int main()

上述**中,我在windows上進行編譯,可以編譯通過

在g++下編譯不通過,主要原因:

程式在編譯的時候 windows下vs編譯器只會檢查函式模板的原型是都正確,而不會去檢查函式體是都正確(windows下,linux下會檢測出錯:未定義的"sdssds").

模板原型:

template bool compare(t a,t b)

2.2 模板函式:通過函式模板例項化出的特定型別的函式**

template bool compare(t a,t b)

int main()

compare(100,200):在呼叫點呼叫時會生成下面這樣乙份**,其中型別推導為int.

bool compare(int a,int b)

語法上來講,編譯器編譯時實際上對上面生成的這份**進行編譯

想一下,如果我們不把sdssds這些未定義的字串進行注釋,在windows上編譯可以通過嗎?

bool compare(int a,int b)

compare< double >(99.9,88.0):同樣的也會生成乙份**,其中型別是呼叫者指定的double.

相當於將double傳遞給我們模板的引數列表中的t.

bool compare(double a,double b)

compare< int >(77,666):此時不會再生成int型的函式**,因為上面已經有乙份了.

3.模板的實參推演:

template bool compare(t a,t b)

int main()

在上述**中,我們在例項化函式時,並沒有指定具體的型別,但是編譯並沒有出錯

這是因為編譯器會根據我們實際傳遞的實參的型別推導出來了乙份int型別的**

這個過程我們稱為模板實參推演.

但是,實際上並不推薦大家使用編譯器的實參推演,因為有的時候會出錯

當實參中沒有引數型別怎麼辦;

case 1:

temlatet fun()

上面說過,編譯器生成什麼型別的**的時候是根據呼叫點的 型別引數決定的

但是此時呼叫的時: fun();

這樣並沒有給模板引數列表中的t進行賦值,也沒有實參的傳遞,這樣編譯器就沒法推導出究竟是什麼型別.

1.cc:13:6: error: no matching function for call to 『fun()』

fun();

^1.cc:6:3: note: candidate: templatet fun()

t fun()

^1.cc:6:3: note: template argument deduction/substitution failed:

1.cc:13:6: note: couldn't deduce template parameter 『t』

fun();

case 2 :

temlatet fun(int a,int b)

即使你給該模板傳遞了兩個實參,但是這個兩個實參與型別t沒有半毛錢的關係

編譯器依然推導不出來.

1.cc: in function 『int main()』:

1.cc:13:12: error: no matching function for call to 『fun(int, int)』

fun(100,99);

^1.cc:6:3: note: candidate: templatet fun(int, int)

t fun(int a,int b)

^1.cc:6:3: note: template argument deduction/substitution failed:

1.cc:13:12: note: couldn't deduce template parameter 『t』

fun(100,99);

case 3:

template bool compare(t a,t b)

int main()

第乙個引數是int,第二個引數是浮點型,可是我們模板的引數列表中只有乙個

這樣就產生二義性了,t == int 還是t == double呢.

deduced conflicting types for parameter 『t』 (『int』 and 『double』)

compare(100,220.0);

除非增加一種模板型別引數

template bool compare(t a,e b)

例項化時:

compare(100,99.9); //此時 t==int e== double

綜上所述,我們還是多敲幾個**,老老實實的將需要例項化的型別傳遞給模板.

4.模板的"過載":

#include using namespace std;

template bool compare(t a,t b)

//模板的特例話

template<>

bool compare(int a,int b)

//普通函式

bool compare(int a,int b)

int main()

輸出:nomal function

我們發現模板,模板的特例化以及普通的函式可以共存,呼叫時的優先順序如下:

普通函式最優先:因為最輕量,不需要例項化**;

其次是特例化函式;

最後才考慮根據函式模板去例項化乙份**.

嚴格意義上這不叫過載,因為過載一般指的是同一作用域下,函式名相同引數列表不同的函式,所以我在這裡加個雙引號.

5.模板的非型別引數:

#include using namespace std;

#include //template可以給乙個預設值

templatevoid mysort(t array)

} }}int main()

mysort(array);

//呼叫的時候size當做模板的非型別引數而不是函式的引數

//這就是函式的非型別引數

for (int i = 0; i < 10;++i)

{ cout<非型別引數的特點:

模板非型別引數本身就是常量,所以我們使用的時候不能去修改它的值;

模板非型別引數可以在引數列表中給定乙個預設值;

當然我們不能用變數給模板費型別引數傳值;

不能用浮點數作為非型別引數,整數型別以及整數型別的指標和引用是可以的.

錯誤例項:

int size = 100;

mysort(array); //size是個變數

const int size = 100;//這樣就是ok的

總結幾點:

c 函式模板基礎

1.為什麼會有函式模板 includeusing namespace std 函式的業務邏輯一樣,函式的引數型別不一樣,比如說交換變數的值,變數可以是int型別,也可以是char型別,還可以是double型別 void myswap01 int a,int b void myswap02 char ...

C 基礎 函式模板

模板用於生成不同的東西 函式或者類 在c 中有函式模板和類模板。場景 當我們需要自己實現print函式時,怎麼處理傳入引數型別 double int char,short string 不同的情況呢?函式過載 這意味著你至少要寫兩個以上的函式區支援你的引數型別和個數的變化,而且這種方法不支援擴充套件...

C 基礎 模板基礎與函式模板

求兩個int float char型別的資料的最大值 c裡面要這樣寫 int maxint int x,int y double maxdouble double x,double y char maxchar char x,char y c 使用函式過載 多個同名函式處理多種型別資料的語法現象 可...