1. 程式人生 > >C++(二):函式過載

C++(二):函式過載

5. 函式過載

5.1 概念

函式過載:是函式的一種特殊情況,C++允許在同一作用域中宣告幾個功能類似的同名函式,這些同名函式的 形參列表(引數個數 或 型別 或 順序)必須不同,常用來處理實現功能類似資料型別不同的問題。

int Add(int left, int right)
{
 return left+right;
}
double Add(double left, double right)
{
 return left+right;
}
long Add(long left, long right)
{
 return left+right;
}
int main()
{
 Add(10, 20);
 Add(10.0, 20.0);
 Add(10L, 20L);

 return 0;
}

返回值不同不是函式過載

short Add(short left, short right)
{
 return left+right;
}
int Add(short left, short right)
{
 return left+right;
}

5.2 名字修飾(name Mangling)

在C/C++中,一個程式要執行起來,需要經歷以下幾個階段:預處理、編譯、彙編、連結。

Name Mangling是一種在編譯過程中,將函式、變數的名稱重新改編的機制,簡單來說就是編譯器為了區分 各個函式,將函式通過某種演算法,重新修飾為一個全域性唯一的名稱。

C語言的名字修飾規則非常簡單,只是在函式名字前面添加了下劃線。比如,對於以下程式碼,在最後連結時就會出錯:

int Add(int left, int right);
int main()
{
 Add(1, 2);
 return 0;
}

編譯器會報錯: 

上述Add函式只給了宣告沒有給定義,因此在連結時就會報錯

從報錯結果中可以看到,C語言只是簡單的在函式名前新增下劃線。因此當工程中存在相同函式名的 函式時,就會產生衝突。

由於C++要支援函式過載,名稱空間等,使得其修飾規則比較複雜,不同編譯器在底層的實現方式可能都有差異。

#include<iostream>
using namespace std;
int Add(int x1, int x2);
double Add(double d1, double d2);
int main()
{
	 Add(1, 3);
	 Add(1.2, 2.4);
	 return 0;
}

通過上述錯誤可以看出,編譯器實際在底層使用的不是Add名字,而是被重新修飾過的一個比較複雜的名 字,被重新修飾後的名字中包含了:函式的名字以及引數型別。這就是為什麼函式過載中幾個同名函式要求 其引數列表不同的原因。只要引數列表不同,編譯器在編譯時通過對函式名字進行重新修飾,將引數型別包 含在最終的名字中,就可保證名字在底層的全域性唯一性。

5.3 extern “C”

有時候在C++工程中可能需要將某些函式按照C的風格來編譯,在函式前加extern "C",意思是告訴編譯器, 將該函式按照C語言規則來編譯。

1. C語言中為什麼不能支援函式過載:

    C語言的名字修飾規則在函式名前邊簡單的加一個‘_’

2. C++中函式過載底層是怎麼處理的 :

編譯器實際在底層使用的不是直接使用函式名字,而是被重新修飾過的一個比較複雜的名字,被重新修飾後的名字中包含了:函式的名字以及引數型別

3. C++中能否將一個函式按照C的風格來編譯:

可以在函式前加 extern "C"