1. 程式人生 > >【共讀Primer】58.[6.5]參數匹配 Page217

【共讀Primer】58.[6.5]參數匹配 Page217

不存在 事情 int 屬於 short ima 轉化 傳遞 就是

一般來說函數的選擇是比較明確的事情,因為有著參數類型和參數數量的標準。

但是如果將類型轉換和默認參數都加入到重載函數中,這個過程就變的復雜起來。

來看看一下代碼:

void f();
void f(int);
void f(int ,int);
void f(double, double = 3.14);

在函數的選擇過程中分為兩步:

1. 找到當前作用域可見的所有名稱相同的函數

2. 找到參數數量相等類型相同或可轉換的函數

f(5.6); // 調用 void f(double, double)

那麽在一些極端情況下還存在第三部:

3. 尋找最佳匹配

我們知道int和double這兩個內置類型是可以進行轉化的,所以對上面的函數調用

如果不存在void f(double, double = 3.14), 那麽void f(int) 將會被調用

這裏void f(double, double=3.14)就是最佳匹配,

那麽我們來看看一個更復雜的情況

f(42, 2.56); // 這個調用完全沒有精確的匹配函數,編譯器應該如何選擇?

我們來編碼實際操作一下:

#include <iostream>

void f(){std::cout << "f()" << std::endl;};
void f(int){std::cout << "f(int)" << std::endl;};
void f(int, int){std::cout << "f(int, int)" << std::endl;}; void f(double, double = 3.14){std::cout << "f(double, double = 3.14)" << std::endl;}; int main() { f(5.6); f(42, 2.56); }

對於上面的代碼編譯情況如下, 意思是編譯器也不知道改掉用哪個,兩者處於平等位置,沒有最優調用

在此類重載的選擇上的原則是

1. 每個參數匹配都不劣於其他的函數匹配。

2. 至少有一個參數的匹配優於其他函數

而本次我們寫的調用,

針對第一個參數來說f(int, int) 更匹配,但是第二個參數需要做轉換。

針對第二個參數來說f(double,double=3.14)更匹配,但是第一個參數需要轉換。

所以對於編譯器來說兩個可行函數的優劣沒有區別,無法進行更優選擇,則產生二義性錯誤。

技術分享圖片

#include <iostream>

void f(){std::cout << "f()" << std::endl;};
void f(int){std::cout << "f(int)" << std::endl;};
void f(int, int){std::cout << "f(int, int)" << std::endl;};
void f(double, double = 3.14){std::cout << "f(double, double = 3.14)" << std::endl;};

int main()
{
    f(5.6);
    // f(42, 2.56);
}

本次代碼編譯運行結果如下:

技術分享圖片

實參類型轉換

而在參數匹配的過程中類型轉換也被劃分為幾個級別:

1. 精確匹配

以下情形屬於精確匹配 :

a. 實參類型和形參類型相同

b. 實參從數組類型或函數類型轉換成對應的指著那類型

c. 向實參添加頂層const或者從實參刪除頂層const

2. 通過const轉換實現的匹配

3. 通過類型提示鞥實現的匹配

4. 通過算術類型轉換或指針轉換實現的匹配

5. 通過類類型轉換實現的匹配

以上的所有情況從上到下的每級的匹配程度低於上一級。

在轉換過程中,遵循的原則是從小向打的轉換

如short和int的兩個匹配類型中如果都需要轉換,通常會選擇int

void ff(int);
void ff(short);
ff(a); // char提升為int

而在算數類型的轉換中並沒有高低的區別。

void manip(long);
void manip(float);
manip(3.14); // 調用將產生二義性

const和參數匹配

非const參數可以作為const實參進行傳遞,但是const實參不能作為非const參數 傳遞。

所以當一個函數有const和非const兩個版本時,那麽將根據參數的精確類型來匹配。

否則將可以使用非const實參調用const形參的函數

void lookup(Account &);
void lookup(const Account&);
const Account a;
Account b;

lookup(a);  // 這個參數只能通過lookup(const Account&)來調用    
lookup(b);  // 這個參數兩個重載都可以調用,但lookup(Account&)匹配更精確

【共讀Primer】58.[6.5]參數匹配 Page217