過載函式引數的轉換和匹配

2021-04-21 15:08:08 字數 2910 閱讀 7757

為了確定最佳匹配,編譯器將實參型別到相應形參型別轉換劃分等級。轉換等級以降序排列如下:

1、精確匹配。實參與形參型別相同。

2、通過型別提公升實現的匹配(第 5.12.2 節)。

3、通過標準轉換實現的匹配(第 5.12.3 節)。

4、通過類型別轉換實現的匹配(第 14.9 節將介紹這類轉換)。

型別提公升或轉換適用於實參型別可通過某種標準轉換提公升或轉換為適當的形參型別情況。

必須注意的乙個重點是較小的整型提公升為 int 型。假設有兩個函式,乙個的形參為 int 型,另乙個的形參則是 short 型。對於任意整型的實參值,int 型版本都是優於 short 型版本的較佳匹配,即使從形式上看 short 型版本的匹配較佳:

void ff(int);

void ff(short);

ff('a'); // char promotes to int, so matches f(int)

字元字面值是 char 型別,char 型別可提公升為 int 型。提公升後的型別與函式 ff(int) 的形參型別匹配。char 型別同樣也可轉換為 short 型,但需要型別轉換的匹配「劣於」需要型別提公升的匹配。結果應將該呼叫解釋為對 ff (int) 的呼叫。

通過型別提公升實現的轉換優於其他標準轉換。例如,對於 char 型實參來說,有 int 型形參的函式是優於有 double 型形參的函式的較佳匹配。其他的標準轉換也以相同的規則處理。例如,從 char 型到 unsigned char 型的轉換的優先順序不比從 char 型到 double 型的轉換高。再舉乙個具體的例子,考慮:

extern void manip(long);

extern void manip(float);

manip(3.14); // error: ambiguous call

字面值常量 3.14 的型別為 double。這種型別既可轉為 long 型也可轉為 float 型。由於兩者都是可行的標準轉換,因此該呼叫具有二義性。沒有哪個標準轉換比其他標準轉換具有更高的優先順序。

回顧列舉型別 enum,我們知道這種型別的物件只能用同一列舉型別的另乙個物件或乙個列舉成員進行初始化(第 2.7 節)。整數物件即使具有與列舉元素相同的值也不能用於呼叫期望獲得列舉型別實參的函式。

enum tokens ;

void ff(tokens);

void ff(int);

int main()

傳遞字面值常量 128 的函式呼叫與有乙個 int 型引數的 ff 版本匹配。

雖然無法將整型值傳遞給列舉型別的形參,但可以將列舉值傳遞給整型形參。此時,列舉值被提公升為 int 型或更大的整型。具體的提公升型別取決於列舉成員的值。如果是過載函式,列舉值提公升後的型別將決定呼叫哪個函式:

void newf(unsigned char);

void newf(int);

unsigned char uc = 129;

newf(virtual); // calls newf(int)

newf(uc); // calls newf(unsigned char)

列舉型別 tokens 只有兩個列舉成員,最大的值為 129。這個值可以用 unsigned char 型別表示,很多編譯器會將這個列舉型別儲存為 unsigned char 型別。然而,列舉成員 virtual 卻並不是 unsigned char 型別。就算列舉成員的值能儲存在 unsigned char 型別中,列舉成員和列舉型別的值也不會提公升為 unsigned char 型別。

在使用有列舉型別形參的過載函式時,請記住:由於不同列舉型別的列舉常量值不相同,在函式過載確定過程中,不同的列舉型別會具有完全不同的行為。其列舉成員決定了它們提公升的型別,而所提公升的型別依賴於機器。

僅當形參是引用或指標時,形參是否為 const 才有影響。

可基於函式的引用形參是指向 const 物件還是指向非 const 物件,實現函式過載。將引用形參定義為 const 來過載函式是合法的,因為編譯器可以根據實參是否為 const 確定呼叫哪乙個函式:

record lookup(account&);

record lookup(const account&); // new function

const account a(0);

account b;

lookup(a); // calls lookup(const account&)

lookup(b); // calls lookup(account&)

如果形參是普通的引用,則不能將 const 物件傳遞給這個形參。如果傳遞了 const 物件,則只有帶 const 引用形參的版本才是該呼叫的可行函式。

如果傳遞的是非 const 物件,則上述任意一種函式皆可行。非 const 物件既可用於初始化 const 引用,也可用於初始化非 const 引用。但是,將 const 引用初始化為非 const 物件,需通過轉換來實現,而非 const 形參的初始化則是精確匹配。

對指標形參的相關處理如出一轍。可將 const 物件的位址值只傳遞給帶有指向 const 物件的指標形參的函式。也可將指向非 const 物件的指標傳遞給函式的 const 或非 const 型別的指標形參。如果兩個函式僅在指標形參時是否指向 const 物件上不同,則指向非 const 物件的指標形參對於指向非 const 物件的指標(實參)來說是更佳的匹配。重複強調,編譯器可以判斷:如果實參是 const 物件,則呼叫帶有 const* 型別形參的函式;否則,如果實參不是 const 物件,將呼叫帶有普通指標形參的函式。

注意不能基於指標本身是否為 const 來實現函式的過載:

f(int *);

f(int *const); // redeclaration

此時,const 用於修改指標本身,而不是修飾指標所指向的型別。在上述兩種情況中,都複製了指標,指標本身是否為 const 並沒有帶來區別。正如前面第 7.8 節所提到的,當形參以副本傳遞時,不能基於形參是否為 const 來實現過載。

過載函式的引數匹配與轉換

過載函式匹配步驟 1 候選函式的確定 與被調函式同名的函式 2 選擇可行函式 在候選函式中,選擇可以呼叫的函式 1 引數個數與被調函式引數個數相等 2 實參型別與形參型別匹配或者可以隱式型別轉換 3 選擇最佳匹配 其每個實參匹配都不劣於其他可行函式需要的匹配 至少有乙個實參的匹配優於其他可行函式的匹...

函式過載和函式的預設引數

函式過載 如果同乙個作用域內的幾個函式名字相同但形參列表不同,我們稱之為過載函式。main函式不能過載。返回值不能用來判斷函式是否過載。引數列表不同 引數的個數不同 引數的型別不同 引數的順序不同 void print int a void print double b int print int ...

C 過載函式(函式匹配與實參型別轉換)

1,函式匹配 過載確定 過載確定的三個步驟 1 候選函式 2 選擇可行函式 3 尋找最佳匹配 比較特殊的是print 3.14 它的引數是double型別,但是選擇候選函式的時候,因為沒有最完美匹配,只能丟失精度,強制轉換為int型別。還有print 3.2,1 這種型別,因為目標函式不唯一,有二義...