C++重載——同名函數的禮讚

C++ 不允許變量重名,但是允許多個函數取相同的名字,只要參數表不同即可,這叫作函數的重載(其英文是 overload)。重載就是裝載多種東西的意思,即同一個事物能完成不同功能。

函數的重載使得 C++ 程序員對完成類似功能的不同函數可以統一命名,減少了命名所花的心思。例如,可能會需要一個求兩個整數的最大值的函數,也可能還要寫一個求三個實數的最大值的函數,這兩個函數的功能都是求最大值,那麼就都命名為 Max 即可,不需要一個命名為 MaxOfTwoIntegers,另一個命名為 MaxOfThreeFloats。

在調用同名函數時,編譯器怎麼知道到底調用的是哪個函數呢?編譯器是根據函數調用語句中實參的個數和類型來判斷應該調用哪個函數的。因為重載函數的參數表不同,而調用函數的語句給出的實參必須和參數表中的形參個數和類型都匹配,因此編譯器才能夠判斷出到底應該調用哪個函數。例如下面的程序:

#include <iostream>
using namespace std;
void Max(int a, int b)
{
cout << "Max 1" << endl;
}
void Max(double a, double b)
{
cout << "Max 2" << endl;
}
void Max(double a, double b, double c)
{
cout << "Max 3" << endl;
}
int main()
{
Max(3, 4); //調用 int Max(int, int)
Max(2.4, 6.0); //調用 double Max(doubleA double)
Max(1.2, 3.4, 5); //調用 double Max(double, double, double)

Max(1, 2, 3); //調用 double Max(double, double, double)
Max(3, 1.5); //編譯出錯:二義性
return 0;
}
/<iostream>

以上程序如果去掉第 21 行編譯出錯的語句,輸出結果是:

Max 1

Max 2

Max 3

Max 3

顯然,編譯器根據調用 Max 函數的語句所給的實參的個數和類型,可以找到完全匹配的函數。例如第 17 行,實參是兩個整型數,那麼調用的當然就應該是原型為 void Max(int, int) 的那個 Max 函數。

第 21 行編譯會出錯,因為兩個實參一個是整型,一個是實數型。如果將整型自動轉換成 實數型,那麼看來應該調用 void Max(double, double) 這個函數;可是如果將實數型去尾自動轉換為整型,那麼調用 void Max(int, int) 似乎也說得過去。

C++ 設計者認為,此時編譯器應該因不知如何選擇而報告二義性的錯誤,而不是規定優先選擇其中某一種。因為如果硬性規定的話,程序員很可能記不清到底編譯器是怎麼規定的,從而可能導致程序員心裡認為應該調用這個 Max 函數,實際上編譯器的處理是調用另一個 Max 函數,結果程序員因編譯器不會報錯而無法察覺這個問題。好的工具總是應該讓使用者少犯錯誤,或者犯了錯誤也能馬上發現。

如果去掉 void Max(int, int) 函數或者 void Max(double, double) 函數中的任何一個,則第 21 行就不會導致編譯時的二義性錯誤了,因為此時實參該如何自動轉換才能和 Max 函數匹配是確定的。

在兩個函數同名而參數個數不同,但是其中參數多的那個函數的參數又可以取默認值的情況下,也可能會引發二義性。例如下面兩個函數:

int Sum(int a, int b, int c = 0);
int Sum(int a, int b);

則函數調用語句:

Sum (1, 2);

就會在編譯時導致二義性錯誤。因為編譯器不知道是應該以 (1, 2, 0) 作為參數調用第一個 Sum 函數,還是以 (1, 2) 作為參數調用第二個 Sum 函數。同樣,將編譯器設計成在這種情況下優先選擇某一種也是不合理的。

需要強調一點,同名函數只有參數表不同才能算重載。兩個同名函數的參數表相同而返回值類型不同不是重載,而是重複定義,是不允許的。

【示例】藉助函數重載交換不同類型的變量的值:

#include <iostream>

using namespace std;

//交換 int 變量的值

void Swap(int *a, int *b){

int temp = *a;

*a = *b;

*b = temp;

}

//交換 float 變量的值

void Swap(float *a, float *b){

float temp = *a;

*a = *b;

*b = temp;

}

//交換 char 變量的值

void Swap(char *a, char *b){

char temp = *a;

*a = *b;

*b = temp;

}

//交換 bool 變量的值

void Swap(bool *a, bool *b){

char temp = *a;

*a = *b;

*b = temp;

}

int main(){

//交換 int 變量的值

int n1 = 100, n2 = 200;

Swap(&n1, &n2);

cout<

//交換 float 變量的值

float f1 = 12.5, f2 = 56.93;

Swap(&f1, &f2);

cout<

//交換 char 變量的值

char c1 = 'A', c2 = 'B';

Swap(&c1, &c2);

cout<

//交換 bool 變量的值

bool b1 = false, b2 = true;

Swap(&b1, &b2);

cout<

return 0;

}

運行結果:

200, 100

56.93, 12.5

B, A

1, 0

原文地址:

http://c.biancheng.net/view/201.html


分享到:


相關文章: