徹底理清過載函式匹配

2021-10-13 21:35:12 字數 2690 閱讀 9142

前面我們講到了《什麼是函式過載?》,有了函式過載之後,就需要確定某次呼叫需要選用哪個函式。這個過程可以稱之為函式匹配或者過載確定。大多數情況下,我們都很容易能夠確定某次呼叫需要選用哪個函式,但事實上不盡然。但通過本文將徹底理清過載函式匹配

為便於說明,將函式匹配分為三個階段,確定候選函式,確定可行函式,確定最佳匹配函式。

確定候選函式

候選函式也就是和被呼叫的函式同名,並且其宣告在呼叫點可見。舉個簡單的例子。

假設有兩個檔案,1.cpp和2.cpp,內容分別如下:

1.cpp:

//函式1

void f(int a,short b)

{     cout<<"func0"<2.cpp:

#includeusing namespace std;

//函式2

void f(int a,double b)

{     cout<<"func1"《在這裡,候選函式其實只有兩個,其中第乙個函式在其呼叫點不可見,而第四個函式和被呼叫的函式不同名,因此這兩個都不是候選函式。

確定可行函式

可行函式指的是本次呼叫傳入的實參能夠被候選函式使用。它要滿足兩個條件,一是形參數量和實參數量相同,二是每個實參的型別和對應形參型別相同或者能夠轉換成形參的型別。

還是前面的例子,實參的個數和型別與第二個函式完全匹配,而在經過算術轉換之後,也能夠與第三個函式匹配。

確定最佳匹配函式

最佳匹配的函式是最終呼叫的。最佳匹配最基本的思想是認為,實參型別越接近,它們就越匹配。還是前面的例子,實參要與第三個函式匹配,需要進行算術轉換,而與第二個函式完全匹配,因此第二個函式是最佳匹配函式。最終的執行結果如下:

func1

一般來說,精確匹配肯定比需要型別轉換的匹配要更好,但是當形參有多個,並且無法完全精確匹配的時候,要確定最佳匹配函式就有點困難了。

但是有下面的原則:

那麼問題又來了,什麼是更好,什麼又是更差呢?編譯器將實參型別到形參型別的轉換劃分了等級:

等級越靠前,匹配也就越好。接下來對上面的內容做一些解釋。

精確匹配

精確匹配比較容易理解。關於頂層const問題,可以參考《什麼是函式過載?》

通過const轉換實現的匹配

所謂通過const轉換實現的匹配,指的是通過加const限定詞,能夠與可行函式精確匹配。例如:

#include using namespace std;

//函式1

/*int f(string &a)

{    cout<<"call function 1"《在這裡,test可以通過const轉換,從而匹配函式2,將能夠找到最佳匹配函式2(當前情況它也只有乙個可選了)。

執行結果如下:

call function 2

如果把函式1的注釋去掉再執行,就會發現,雖然第乙個呼叫既能匹配函式1,也能匹配函式2,但是由於匹配函式2的時候,需要const轉換,因此比精確匹配要差,最終,它會呼叫函式1。

去掉函式1的注釋後,執行結果如下:

call function 1
通過型別提公升實現的匹配

關於型別提公升,這裡不多做介紹。簡單說明型別提公升規則:

我們來看乙個示例:

#include using namespace std;

//函式1

/*int f(short a)

{    cout<<"call function 1"《同樣地,我們暫時把函式1注釋掉。由於a是short型別,但是通過型別提公升,可以轉換為int,因為它也能呼叫函式2。執行結果如下:

call function 2

但去掉函式1注釋後,由於精確匹配優於通過型別提公升的匹配,因此將會呼叫函式1,執行結果如下:

call function 1
通過算術型別轉換實現的匹配

short int和float,double等之間的轉換,都是算術型別之間的轉換。我們仍然來看乙個例子:

#include using namespace std;

//函式1

int f(int a)

{    cout<<"call function 1"《在這裡,short型別的a既可以通過型別提公升轉換為int,也可以通過算術型別轉換成為double。這個時候,哪個才是最佳匹配呢?我們看執行結果:

call function 1

對於這個結果,並不意外,因為前面我們已經說到,通過型別提公升的轉換是優於算術轉換的,因而函式1是它的最佳匹配函式。

通過類型別轉換實現的匹配

這裡不多做介紹。我們也很容易理解。諸如父類和子類之間的轉換都是如此。

前面基本能夠找到最佳匹配,我們來看乙個有多個可行函式,最後卻沒有最佳匹配的情況。

#includeusing namespace std;

//函式1

void f(double a,int b)

{     cout<<"function 1"《函式1和函式2都是可行函式,但它們都沒有在任意乙個引數上比對方更好,因此將會產生二義性,編譯時將會報錯:

error: call of overloaded 『f(int, int)』 is ambiguous

C 函式過載與函式匹配

c primer 筆記,整理關於函式過載與函式匹配的筆記。void func int a 原函式 void func double a 正確 形參型別不同 void func int a,int b 正確 形參個數不同 int func int a 錯誤 只有返回型別不同 typedef int i...

c 之函式過載 函式匹配

case void f void f int void f int,int void f double,double 3.14 匹配原則 1 其形參數量與本次呼叫提供的實參數量相等 2 每個實參的型別與對應的形參型別相同,或者可以轉換成形參的型別 尋找最佳匹配 1 該函式每個實參的匹配都不劣於其他可...

c 函式過載與匹配

匹配規則 精確匹配 常量版本匹配 變數提公升 算數 指標轉換 類型別轉換 當我們為函式過載,並呼叫過載後的函式時,編譯器會自動根據引數型別進行匹配與轉換但是此時 容易出現二義性錯誤,函式引數轉換與型別提公升容易混淆,例如當我們同時過載了float double 版本的函式時,傳入乙個int型實參,就...