C++富有價值的函數重載,零基礎上手,一文解析C++函數重載


C++富有價值的函數重載,零基礎上手,一文解析C++函數重載

在實際開發中,有時候我們需要實現幾個功能類似的函數,只是有些細節不同。例如希望交換兩個變量的值,這兩個變量有多種類型,可以是 int、float、char、bool 等,我們需要通過參數把變量的地址傳入函數內部。在C語言中,程序員往往需要分別設計出三個不同名的函數,其函數原型與下面類似:

<code> void swap1(int *a, int *b);      //交換 int 變量的值
void swap2(float *a, float *b); //交換 float 變量的值
void swap3(char *a, char *b); //交換 char 變量的值
void swap4(bool *a, bool *b); //交換 bool 變量的值/<code>

但在C++中,這完全沒有必要。C++ 允許多個函數擁有相同的名字,只要它們的參數列表不同就可以,這就是函數的重載(Function Overloading)。藉助重載,一個函數名可以有多種用途。

參數列表又叫參數簽名,包括參數的類型、參數的個數和參數的順序,只要有一個不同就叫做參數列表不同。【示例】藉助函數重載交換不同類型的變量的值:

<code>#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 << n1 << ", " << n2 << endl;
//交換 float 變量的值
float f1 = 12.5, f2 = 56.93;
Swap(&f1, &f2);
cout << f1 << ", " << f2 << endl;
//交換 char 變量的值
char c1 = 'A', c2 = 'B';
Swap(&c1, &c2);
cout << c1 << ", " << c2 << endl;
//交換 bool 變量的值
bool b1 = false, b2 = true;
Swap(&b1, &b2);
cout << b1 << ", " << b2 << endl;
return 0;
}/<iostream>/<code>

運行結果:

C++富有價值的函數重載,零基礎上手,一文解析C++函數重載

本例之所以使用Swap這個函數名,而不是使用swap,是因為 C++ 標準庫已經提供了交換兩個變量的值的函數,它的名字就是swap,位於algorithm頭文件中,為了避免和標準庫中的swap衝突,本例特地將S大寫。

既然標準庫已經提供了 swap() 函數,本例為何又要自己實現一遍呢,這不是費力不討好嗎?交換兩個變量的值是一個經典且實用的函數重載案例,本例這樣做僅僅是為了教學演示,並不是要替代標準庫中的 swap(),讀者在以後的編碼過程中也應該堅持使用標準庫中的 swap()。

通過本例可以發現,重載就是在一個作用範圍內(同一個類、同一個命名空間等)有多個名稱相同但參數不同的函數。重載的結果是讓一個函數名擁有了多種用途,使得命名更加方便(在中大型項目中,給變量、函數、類起名字是一件讓人苦惱的問題),調用更加靈活。

在使用重載函數時,同名函數的功能應當相同或相近,不要用同一函數名去實現完全不相干的功能,雖然程序也能運行,但可讀性不好,使人覺得莫名其妙。

注意,參數列表不同包括參數的個數不同、類型不同或順序不同,僅僅參數名稱不同是不可以的。函數返回值也不能作為重載的依據。

  • 函數的重載的規則:
  • 函數名稱必須相同。
  • 參數列表必須不同(個數不同、類型不同、參數排列順序不同等)。
  • 函數的返回類型可以相同也可以不相同。
  • 僅僅返回類型不同不足以成為函數的重載。
C++富有價值的函數重載,零基礎上手,一文解析C++函數重載

C++ 是如何做到函數重載的

C++代碼在編譯時會根據參數列表對函數進行重命名,例如void Swap(int a, int b)會被重命名為_Swap_int_int,void Swap(float x, float y)會被重命名為_Swap_float_float。當發生函數調用時,編譯器會根據傳入的實參去逐個匹配,以選擇對應的函數,如果匹配失敗,編譯器就會報錯,這叫做重載決議(Overload Resolution)。

不同的編譯器有不同的重命名方式,這裡僅僅舉例說明,實際情況可能並非如此。

從這個角度講,函數重載僅僅是語法層面的,本質上它們還是不同的函數,佔用不同的內存,入口地址也不一樣。

C++富有價值的函數重載,零基礎上手,一文解析C++函數重載

隱式類型轉換導致重載函數二義性的問題

例如函數形參的類型是int,調用函數時卻將short類型的數據交給了它,編譯器就需要先將short類型轉換為int類型才能匹配成功。

注意,類型提升和類型轉換不是一碼事!類型提升是積極的,是為了更加高效地利用計算機硬件,不會導致數據丟失或精度降低;而類型轉換是不得已而為之,不能保證數據的正確性,也不能保證應有的精度。

函數重載二義性錯誤代碼示例:

<code>#include <iostream>
using namespace std;

void func(int, int) {};
void func(char, int, float) {};
void func(char, long, double) {};

int main() {
short n = 99;
func(n, n);
func('@', n, 99);
func('@', n, 99.5); //二義性錯誤
getchar();
return 0;
}/<iostream>/<code>

VS報錯提示:

C++富有價值的函數重載,零基礎上手,一文解析C++函數重載

所以,大家在寫函數重載時一定要注意,還有一個問題,函數重載和默認參數一起使用時也可能出問題,請大家多多實踐

尾言

文章都是手打原創,每天最淺顯的介紹C語言、C++,windows知識,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。如果足下基礎比較差,不妨關注下人人都可以學習的視頻教程

通俗易懂,深入淺出,一個視頻只講一個知識點。視頻不深奧,不需要鑽研,在公交、在地鐵、在廁所都可以觀看,隨時隨地漲姿勢


分享到:


相關文章: