C 函式的模板與過載解析

2021-08-28 04:58:43 字數 3153 閱讀 7880

模板是c++泛型程式設計的基礎,乙個模板就是乙個建立類或者函式的方案。在具體使用時,需要將模板引數轉化為具體型別。編譯器會對函式模板進行兩次編譯,在宣告的地方對模板本身進行編譯,在呼叫的地方對引數替換後的**進行編譯。

c++提供兩種模板機制:函式模板和類模板,這裡我們只討論函式模板。

1,例項化和具體化

為了更好的了解模板,我們必須理解術語例項化和具體化。模板是生成函式定義的方案,編譯器使用模板為特定的型別生成函式定義時,得到模板的例項(具體型別的函式實現)。

1.1,例項化

首先我們來聊一聊例項化,例項化可以分為顯式例項化和隱式例項化。不管是哪一種例項化方式,都需要編譯器通過模板來生成定義。

顯式例項化,由我們指定typename ;隱式例項化,由編譯器自動推導typename。

tamplate 

void swap(t &a,t &b)

//隱式例項化:

char a,b;

swap(a,b); //直接呼叫,a,b的型別並沒有顯式例項化宣告

//typename 由編譯器自動推導

//顯式例項化:

//1,宣告階段顯式例項化:

tamplate swap (int,int);

int c,d;

swap(c,d);

//2,呼叫階段顯式例項化:

swap (c,d); //不做聲明,直接通過swap指定型別

注意:隱式例項化呼叫時,需要編譯器自動推導typename 型別,所以引數不能進行隱式轉換。顯式例項化呼叫時,可以進行隱式轉換,如果轉換不成功,則無法呼叫模板。

1.2,具體化

具體化是為了解決模板函式面對自定義資料型別時候的侷限性。

上文提到過,不管是哪一種例項化方式,都需要編譯器通過模板來生成定義。但是具體化,需要我們給出函式的定義

一般情況下,c++基本資料型別(int,char)都可以採用顯式或隱式例項化呼叫;自定義資料型別(class,struct)需要做出顯式具體化,而不是由編譯器根據模板生成定義。

//以下兩種方式皆可:

template

<> void swap(job &a, job &b);

template

<> void swap(job &a, job &b);

struct job;};

//顯式具體化,給出函式定義。

template

<> void swap(job &a, job &b)

//呼叫時:

swap(job1,job2);

第三代具體化(iso/anxi c++標準):2,解析策略對於函式過載,函式模板,函式模板過載,c++有一套定義好的策略,來決定為函式呼叫選擇哪乙個函式定義。這個函式選擇的過程,稱為過載解析。以下是過載解析的過程:

建立候選函式列表。其中包含所有與被調函式的名稱相同的函式和模板函式。

使用候選函式列表建立可行函式列表。這些都是引數數目正確的函式,為此有乙個隱式轉換序列,其中可能包含實參與形參的型別完全匹配的情況。

確定是否由最佳可行函式,如果有則使用它,否則函式呼叫出錯。

void may(int);                      //#1

float may(float,float = 0) //#2

void may(char) //#3

char * may(const

char *) //#4

char may(const

char &) //#5

template

void may(const t &)//#6

template

void may(t *) //#5

//函式呼叫如下:

may('a');

執行過載解析:

1,根據上邊的候選函式列表,#4和#7不可行,整形不能隱式轉換為指標型別

2,其餘的函式,都可以被使用(如果它是宣告的唯一乙個函式)

3,確定哪個函式是最佳函式(檢視轉換)

4,#1優於#2,char=>int(提公升轉換),char=>float(標準轉換)

5,#3,#5,#6 都優於#1,#2,因為他們都是完全匹配的。

6,#3,#5由於#6,因為#6是模板函式

7,此時#3,#5都完全匹配,此時可能出現二義性

注意:完全匹配和最佳匹配:

進行完全匹配時,c++允許一些無關緊要的轉換。

有時候兩個函式都完全匹配,但是仍可能完成過載解析

1,指向 非const的指標和引用優先 與 非const的指標和引用的形參原型函式相匹配。const與const優先匹配

2,非模板函式優先於模板函式

3,如果兩個都是模板函式,較具體的優先

術語:最具體:

編譯器推斷使用哪一種函式原型,需要執行的轉換最少。

例:

template

void recycle(t t); #1

template

void recycle(t* t); #2

//模板呼叫

rec rec; //自定義型別

recycle( &rec)

#1 t需要轉換為 rec *

#2 t需要轉換為 rec

所以說#2更具體

C 中的函式過載與模板

函式就像工具,工具有好多種,我們就以螺絲刀為例來感受一下它和函式過載和模板的一些相似關係。螺絲刀的種類有很多,常見的是一字型和梅花型,每種型別從小到大又有好多個號。我們根據螺絲樣式和大小 選擇使用那種型別的和選擇多大號的螺絲刀。螺絲刀就幹了一件事,擰螺絲,也就是說各種螺絲刀他們的功能是相 同的,只是...

函式過載與模板

提到函式過載想必大家都非常清楚,但是大家是否了解所有細節呢,經過這段時間閱讀 我發現其實我一直以來並未完全理解過載機制,此處做乙個小小的總結 1 首先函式過載是指對函式名的過載,它只在同一作用域中有效,不同作用域中的名字不可構成過載,除非顯示使用using關鍵字將名字引入該作用域。如例所示 void...

函式的過載與函式模板

有時候想要實現幾個功能相近,但只是處理的引數型別不同的函式,在c語言裡我們要把這些函式起上不同的名字,而在c 裡我們可以把這些函式都給上乙個函式名只需要把不同的引數給入函式就可以了,這樣大大的減少了函式名的數量,增強了 的可讀性。c 中這叫做函式的過載,是在同一作用域內宣告幾個功能類似的同名函式,但...