初識C++之函數重載

最近開始學習C++,瞭解到它在C語言沒有的一個特性 – 函數重載,這一特性使得c++的函數數量得以減少,減小了對名字空間的污染,另外對程序的可讀性也有很大幫助。

那麼c++的函數重載這一特性是怎麼實現的,爲什麼不會發生命名衝突呢?別的函數在調用這些函數時編譯器是怎麼解析的呢?怎麼知道它該調用哪一個函數呢?下面就這些問題來做一些簡單解析。

1、什麼是函數重載

C++允許在同一作用域內聲明並實現幾個名稱相同,功能相似的函數,但必須保證這些函數的參數列表不同(參數個數不同、參數類型不同或者參數順序不同)

根據上面的定義,判斷哪些是正確的函數重載,哪些是錯誤的:

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

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

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

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

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

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

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

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

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

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

①②③很容易得出都是正確的函數重載;
④乍一看,很像是滿足了參數順序不同這一條件,但仔細分析一下,函數在定義或聲明是是可以省略參數名的,因爲編譯器只檢查函數參數的類型與個數,並不會檢查函數名。那麼,④的兩個函數就可以看做是一個,因爲它們無法構成函數重載;
⑤看起來也很像啊,但它滿足函數重載的任何要求了嗎,另個函數參數列表完全是一樣的,唯一不一樣的就是函數的返回值不同,但僅僅返回不同是無法構成函數重載的的,因此,它們也無法構函數重載。

2、爲什麼需要函數重載

想一想我們的C語言裏是怎麼定義不同類型的數據的加法函數的:

int Add(int a, int b); –> int 型數據的加法函數
short Add(short a, short b); –> short 型數據的加法函數
double Add(double a, double b); –> double 型數據的加法函數

是不是感覺很麻煩,都是同一功能的函數,卻要起不同的名字,正式基於這一點,c++允許實現函數重載,這樣不僅同一功能的函數都能叫同一名字,而且節省了名字空間。

3、編譯器如何解決函數重載的命名衝突

c++確實能支持函數重載,但編譯器是怎麼處理這種特性,使它們在編譯後不會出現名字衝突的呢?

這裏可以參考我的另一篇博客:
重載函數編譯後的新名字
http://blog.csdn.net/ljx_5489464/article/details/50981773

4、編譯器如何解析重載函數的調用呢?

上面我們知道了,編譯器通過一定的機制使重載函數在編譯後不會發生名字衝突,那麼在調用這些重載的函數時,編譯器是如何知道該調用哪一個的呢?

編譯器一般需要依次按照下列規則來判斷:
a. 精確匹配:參數列表完全匹配,或者只是做微不足道的轉換,如數組名到指針、函數名到指向函數的指針、T到const T;
b. 提升匹配:即整數提升(如bool 到 int、char到int、short 到int),float到double
c. 使用標準轉換匹配:如int 到double、double到int、double到long double、Derived*到Base*、T*到void*、int到unsigned int;
d. 使用用戶自定義匹配;
e. 使用省略號匹配:類似printf中省略號參數

通過以上規則來進行選擇:
①根據函數名確定候選函數集
②確定可用函數
③確定最佳匹配函數

如果在最有多個最佳匹配函數找到,調用將被拒絕(因爲有歧義、模凌兩可)。

本文參考:
http://www.cnblogs.com/skynet/archive/2010/09/05/1818636.html

發佈了68 篇原創文章 · 獲贊 80 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章