C++中的函數重載(Overroad)
/*
*運行平臺:Visual Studio 2015(Debug x86)
*參考資料:《C++ Primer Plus(第6版)》,傳智掃地增C++基礎課程
*/
目錄
一、前言
俗話說,人靠衣裝馬靠鞍,一套好看的衣服搭配可以讓人煥然一新。
同理,一套合理的函數重載也可以使編譯器更好的根據數據類型處理問題。
我們可以通過每天的衣服搭配 類比 函數重載,即一個星期中可以根據星期幾,搭配不同的衣服方案。
實物 | 類比爲 |
---|---|
人的性格 | 函數返回值 |
人的名字 | 函數名 |
每天的衣服搭配方案 | 參數列表 |
衣服件數 | 參數個數 |
衣服款式 | 參數的數據類型 |
二、概念
重載函數是函數的一種特殊情況,爲方便使用,C++允許在同一範圍中聲明幾個功能類似的同名函數,但是這些同名函數的形式參數(指參數的個數、類型或者順序)必須不同,也就是說用同一個函數完成不同的功能。
總結:
- 用同一個函數名定義不同的函數——一個人每天可以搭配不同的衣服。
- 當函數名和不同的參數搭配時函數的含義不同——衣服的搭配,隨每天的變化而變化。
二、如何使用
1、滿足條件
函數重載至少滿足下面的一個條件:
- 參數個數不同——衣服件數不同
- 參數類型不同——衣服款式不同
- 參數順序不同(同時類型不同)——疊穿衣服效果
2、使用方法
2.1 參數個數不同——衣服件數不同
- 代碼如下:
void fun (int a)
{
cout << a << endl;
}
void fun (int a, int b)
{
cout << a << b << endl;
}
void main()
{
int a = 0;
int b = 1;
fun(a);
fun(a,b);
system("pause");
}
- 運行結果:
通過調用函數時的參數個數不同,來執行不同的重載函數——通過穿衣件數,別人(編譯器)來判斷今天搭配的是哪套衣服。
2.2 參數類型不同——衣服款式不同
- 代碼如下:
void fun (int a)
{
cout << a << endl;
}
void fun (char a)
{
cout << a << endl;
}
void main()
{
int a = 0;
char b = 'b';
fun(a);
fun(b);
system("pause");
}
- 運行結果:
通過調用函數時的參數類型不同,來執行不同的重載函數——通過穿衣的款式,別人(編譯器)就可以來判斷今天搭配的是哪套衣服。
2.3 參數順序不同(同時類型不同)——疊穿衣服效果
- 代碼如下:
void fun(int a, char b)
{
cout << a << b << endl;
}
void fun(char a, int b)
{
cout << a << b << endl;
}
void main()
{
int a = 0;
char b = 'b';
fun(a, b);
fun(b, a);
system("pause");
}
- 運行結果:
通過調用函數時的參數順序(同時類型)不同,來執行不同的重載函數——通過穿衣的順序(相當於疊穿衣服會呈現不同的效果),別人(編譯器)來判斷今天搭配的是哪套衣服。
3、注意:函數返回值不是函數重載的判斷標準
前提:參數列表(個數,類型和順序)都一致。
- 代碼如下:
void fun(int a, char b)
{
cout << a << b << endl;
}
int fun(int a, char b)
{
cout << a << b << endl;
return 0;
}
- 運行結果:
此時在你定義完函數時,編譯器就會報錯——當你前後兩天搭配的衣服款式一樣時,就算性格此時不同,但是在別人(編譯器)看來,人還是和昨天的人一樣。
三、難點一:重載函數和默認函數參數混搭
前面我們說過當參數個數不同時,可以重載函數,可是如果出現重載函數和默認函數參數混搭的情況,可以重載成功嗎?
通過實驗證明:
- 代碼如下:
void fun(char a)
{
cout << a << endl;
}
void fun(int a, int b = 0)
{
cout << a << b << endl;
}
void main()
{
int a = 0;
fun(a);
system("pause");
}
- 運行結果:
在程序編譯時,編譯器會報錯。
這個一種特殊情況,千萬記住在編程時不要出現這個錯誤。
四、難點二: 重載函數和函數指針
1、驗證
當使用重載函數名對函數指針進行賦值時,編譯器是如何挑選重載函數的?
通過實驗證明:
- 代碼如下:
void fun(int a)
{
cout << a << endl;
}
void fun(int a,int b)
{
cout << a << b << endl;
}
//聲明一個函數指針類型
typedef void(*MyFun2) (int a);
void main()
{
int a = 1;
int b = 2;
MyFun2 p = fun;
p(a);
system("pause");
}
- 運行結果:
可以看到程序運行了void fun(int a);
這個重構函數。
我們嘗試下把p(a); 改爲 p(a, b);
,可以看到在程序編寫完後,提示錯誤。
2、總結
當使用重載函數名對函數指針進行賦值:
- 根據重載規則挑選與函數指針參數列表一致的候選者
- 嚴格匹配候選者的函數類型與函數指針的函數類型
五、編譯器調用重載函數的準則
- 尋找:將所有同名函數作爲候選者,嘗試尋找可行的候選函數。
- 精確匹配實參:通過默認參數能夠匹配實參 和 通過默認類型轉換匹配實參
- 匹配成功:執行對應的重載函數。
- 匹配失敗:最終尋找到的可行候選函數不唯一,則出現二義性,編譯失敗;無法匹配所有候選者,函數未定義,編譯失敗。