一、函數重載:在相同作用域內的 具有相同函數名不同參數列表(參數個數、類型、順序)的函數構成重載
二、爲什麼要用函數重載
在C中,我們對一個功能函數要實現不同類型的調用時,就必須得取不同的名稱。如果調用的非常多就要起很多名字,這樣就增加了工作量,如果採用函數重載來聲明一組功能相似的函數,這樣做減少了函數名的數量,避免了名字空間的污染,對於程序的可讀性有很大的好處
三、C++函數重載是如何實現的?
在C++的底層,有重命名機制
舉例:
#include<iostream>
using namespace std;
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, 10);
Add(10.0, 10.0);
Add(10L, 10L);
return 0;
}
通過上面的代碼實現,可以根據具體的Add()的參數去調用對應的函數
底層的重命名機制將add函數根據參數的個數,參數的類型,返回值的類型做了重新命名,那麼藉助函數重載,一個函數就有多種命名機制
在C++調用約定(_cdecl 調用約定)中Add函數在底層被解析爲:
"int __cdecl Add(int,int)" (?Add@@YAHHH@Z)
"double __cdecl Add(double,double)" (?Add@@YANNN@Z)
"long __cdecl Add(long,long)" (?Add@@YAJJJ@Z)
在C++ 程序中調用被 C 編譯器編譯後的函數,爲什麼要加 extern “C”聲明?
(1)C++中可以通過在函數聲明前加 extern "C" 將一個函數按照 C 語言的風格來進行編譯。
(2)C++語言支持函數重載。而C不支持函數重載。
(3)函數在C中和C++中編譯過的函數名字是不一樣的。加上extern”C”是說明是說明C已經編譯過的。
C++想要調用已經編譯過的C函數,由於編譯過的名字不同,是不能直接調用的,所以C++加extern“C”生命來解決這個問題。
例如:假設某個函數的原型爲: void foo(int x, int y);該函數被C 編譯器編譯後在庫中的名字爲_foo, 而C++ 編譯器則會產生像_foo_int_int 之類的名字,加上extren”C”後,就相當於告訴編譯器,函數foo是個C編譯後的函數,在庫裏應該找的是_foo,而不是_foo_int_int.
2. 相關面試題
a) C語言爲什麼不支持函數重載
如上的三個Add函數,在C++中被解析爲:
"int __cdecl Add(int,int)" (?Add@@YAHHH@Z)
"double __cdecl Add(double,double)" (?Add@@YANNN@Z)
"long __cdecl Add(long,long)" (?Add@@YAJJJ@Z)
在C語言中被解析爲_Add,三個一樣,所以不能進行區分,因此C語言不支持函數重載
b) C++中函數重載底層是怎麼處理的
底層的重命名機制將Add函數根據參數的個數,參數的類型,返回值的類型都做了重新命名。那麼藉助函數重載,一個函數就有多種命名機制。
在C++調用約定(_cdecl 調用約定)中Add函數在底層被解析爲:
"int __cdecl Add(int,int)" (?Add@@YAHHH@Z)
"double __cdecl Add(double,double)" (?Add@@YANNN@Z)
"long __cdecl Add(long,long)" (?Add@@YAJJJ@Z)
c) C++中能否將一個函數按照C的風格來編譯
C++中可以通過在函數聲明前加 extern "C" 將一個函數按照 C 語言的風格來進行編譯。