C++函數重載實現的機制

一、函數重載:在相同作用域內的 具有相同函數名不同參數列表(參數個數、類型、順序)的函數構成重載

二、爲什麼要用函數重載

  在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 語言的風格來進行編譯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章