重載,顧名思義從字面上理解就是重復裝載,打一個不恰當的比方,你可以用一個籃子裝蔬菜,也可以裝水果或者其它,使用的是同一個籃子,但是可以用籃子重復裝載的東西不一樣。
函數重載是C++多態(靜態多態)的特征體現,它可以允許重復使用同一個函數名(籃子)的函數,但是函數的參數列表(籃子裝的東西)是可以不一樣的。 這樣就可以利用函數的重載功能設計一系列功能相近,但是功能細節不一樣的函數接口。
以同一個函數printData為例:
#include
using namespace std;
void printData(const char *str, int num)
{
//函數體;
}
void printData(const char *str)
{
//函數體;
}
void printData(double data, int num)
{
//函數體;
}
void printData(int data, int num)
{
//函數體;
}
void printData(long data, char num)
{
//函數體;
}
class Test
{
public:
void MyPrint(int num) {cout << "class int: " << num << endl;}
void MyPrint(float num) {cout << "class float: " << num << endl;}
void MyPrint(char num) {cout << "class char: " << num << endl;}
};
int main(void)
{
printData("hello", 5); // (const char *str, int num)
printData("hello"); // (const char *str)
printData(1993.0, 97);
printData(1993, 98);
printData(1993L, 99);
Test test1;
test1.MyPrint(2); // class int: 2
test1.MyPrint(2.0f); // class float: 2.0 浮點型必須要顯式類型,否則編譯器不知道該轉換為int還是float。
test1.MyPrint("hello"); // class char: hello
return 0;
}
使用重載函數時,需要在函數調用中使用與對應的重載函數匹配的函數參數類型。
而如下:
unsigned int para = 4321;
printData(4321, 5);
此時的printData調用和哪個原型匹配呢? 答案它不與任何函數原型匹配,而沒有匹配的原型不會停止調用其中某一個函數,C++會嘗試用標準的強制類型轉換與之匹配,比如使用
printData(double data, int num),就可以將para的類型強制轉換為double類型。 但是還有printData(int data,int num)和printData(long data, char num)這兩個函數可以強制轉換para。 因此,C++將拒絕這種函數的調用,將這種調用視為錯誤。
重載函數通常用在同一個作用域內,用同一個函數名命名一組功能相似的函數,這樣做減少了函數名的數量,提高了函數的通用性,避免了名字空間的污染,對于程序的可讀性有很大的好處。
下面這種兩種情況不能視為函數重載:
int fun(int a);
int fun(int &a);
從編譯器的角度出發,參數a與參數列表原型int a和int &a都匹配,編譯器無法確定使用哪個函數,為避免這種混亂,編譯器在檢查參數類型時將把類型本身和類型引用看作是同一個特征類型。
int fun(int a, float b);
double fun(int a, float b);
C++不允許這樣的方式重載函數,雖然返回值可以不一樣,但是參數列表必須不一樣。
函數重載的使用原則:
(1)、僅當函數的基本功能比較相近,但是需要使用不同形式的參數實現功能時才應該使用函數重載,盡量不要用同一函數名去實現完全不相干的功能;
(2)、在同一個作用范圍內使用函數重載,同一個范圍即:同一個命名空間或者同一個類等;
(3)、重載函數的名稱必須相同,函數的參數列表須不相同,即參數列表中參數的類型,參數的個數或參數的順序不相同;
(4)、重載函數可以有相同的返回值類型或者不同的返回值類型,反之僅僅是返回類型不同不足以作為函數的重載。
常見問題:
1、C++中對函數重載是如何處理的?
在.cpp文件中,雖然兩個函數的函數名一樣,但是,C++編譯器在內部使用“名稱修飾”或“名稱矯正”轉換,它根據函數中參數列表的區別為每個函數進行加密
,例如:
int fun(int a, float b)和double fun(int a, float b)
編譯器在內部可以轉換為:
? fun@@YAHHH@Z和? fun@@YAMMM@Z
"?"表示名稱開始,"?"后邊是函數名; “@@YA”表示參數表開始,后邊的3個字符分別表示返回值類型,兩個參數類型; “@Z”表示名稱結束。
由于在.cpp文件中,兩個函數生成的符號表中字符的名稱不一樣,所以是可以編譯通過的。
2、C語言中為什么不能支持函數重載?
編譯器在編譯.c文件時,只會給函數進行簡單的重命名。 具體的方法是給函數名之前加上”_”; 所以編譯前兩個函數名相同的函數在編譯之后的函數名也照樣相同; 因此調用時會因為不知道到底調用哪個而出錯。
int fun(int a, float b)和double fun(int a, float b)
編譯器在內部都轉換為:_fun,無法區分,
只有不同的函數名字int fun1(int a, float b)和double fun2(int a, float b)
編譯器在內部轉換為:_fun1和_fun2,這才能區分開來。
-
C語言
+關注
關注
180文章
7601瀏覽量
136251 -
函數
+關注
關注
3文章
4308瀏覽量
62444 -
C++
+關注
關注
22文章
2104瀏覽量
73503 -
編譯器
+關注
關注
1文章
1618瀏覽量
49057 -
void
+關注
關注
0文章
23瀏覽量
9858
發布評論請先 登錄
相關推薦
評論