天天看點

c++函數重載的原理

一、什麼是函數重載:         函數重載是指在同一作用域内,可以有一組或者多組具有相同函數名,不同參數的函數,這組函數被稱為重載函數。         重載函數通常用來命名一組功能相似的函數,這樣做減少了函數名的數量及複雜度,避免了名字空間的污染,對于程式的可讀性有很大的好處。

具體的函數例子:

#include <iostream>
using namespace std;
int Add(int a, int b)
{
        return a+b;
}

double Add(double a, double b)
{
        return a+b;
}

int main()
{
       cout<<Add(1, 2)<<endl;
       cout<<Add(1.0, 2.0)<<endl;
       return 0;
}
           

這裡有兩個Add函數,如果實在c語言中,就會出現報錯:

c++函數重載的原理

但是在c++中,它就能編譯過去,且沒有錯誤,這就實作了函數的重載。

二、為什麼要函數重載:    由上一個例子可見: 在c語言當中,如果沒有函數重載,要實作一個相同功能的函數,要使它能夠适應各種類型的資料運算,就要起各種函數的函數名,如:Add_int、 Add_double等待,這樣做無形間就加大了命名的複雜性。

三、c++是如何實作函數重載的: 下面我們開始在linux環境下編譯這個函數,檢視在反彙編下,這些函數的變化:

c++函數重載的原理

上圖是在反彙編情況下int Add函數的命名。

c++函數重載的原理

上圖是在反彙編的情況下double Add函數的命名。

由此可見,在c++的環境下,實作函數重載的手段就是在編譯的時候,将兩個函數名替換成不同的名字,這樣就能避免沖突了。 而由上面的兩個命名,我們也能簡單得發現一點規律:大緻就是_Z開頭,3傳回類型,Add函數名,ii/dd參數。 這點我們可以用另一個函數來試驗證: 我們往上添加一個函數:

double Add(int a, double b)
{
        return a+b;
}
           

按照我們的猜想,在反彙編中輸出的函數名應該是:_Z3Addid。 驗證:

c++函數重載的原理

驗證結果與我們預期一樣。

由上我們就可以來回答一個問題: 在C++ 程式中調用被 C 編譯器編譯後的函數,為什麼要加 extern “C”聲明? 答:c++語言支援函數重載,C語言不支援函數重載。函數被c++編譯後在庫中的名字與c語言的不同。假設某個函數的原型為:void foo(int x, int y);       該函數被c編譯器編譯後在庫中為_foo,而c++編譯器則會産生像_foo_int_int之類的名字。       c++提供了c連接配接交換指定符号extern “C”來解決名字比對問題。

繼續閱讀