C++重載的奧義之函數(shù)重載詳解
一、基本定義
重載,顧名思義從字面上理解就是重復(fù)裝載,打一個不恰當(dāng)?shù)谋确?,你可以用一個籃子裝蔬菜,也可以裝水果或者其它,使用的是同一個籃子,但是可以用籃子重復(fù)裝載的東西不一樣。
函數(shù)重載是C++多態(tài)(靜態(tài)多態(tài))的特征體現(xiàn),它可以允許重復(fù)使用同一個函數(shù)名(籃子)的函數(shù),但是函數(shù)的參數(shù)列表(籃子裝的東西)是可以不一樣的。這樣就可以利用函數(shù)的重載功能設(shè)計一系列功能相近,但是功能細節(jié)不一樣的函數(shù)接口。
二、應(yīng)用舉例
以同一個函數(shù)printData為例:
#include <iostream> using namespace std; void printData(const char *str, int num) { //函數(shù)體; } void printData(const char *str) { //函數(shù)體; } void printData(double data, int num) { //函數(shù)體; } void printData(int data, int num) { //函數(shù)體; } void printData(long data, char num) { //函數(shù)體; } 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 浮點型必須要顯式類型,否則編譯器不知道該轉(zhuǎn)換為int還是float。 test1.MyPrint("hello"); // class char: hello return 0; }
使用重載函數(shù)時,需要在函數(shù)調(diào)用中使用與對應(yīng)的重載函數(shù)匹配的函數(shù)參數(shù)類型。
而如下:
unsigned int para = 4321; printData(4321, 5);
此時的printData調(diào)用和哪個原型匹配呢?答案它不與任何函數(shù)原型匹配,而沒有匹配的原型不會停止調(diào)用其中某一個函數(shù),C++會嘗試用標(biāo)準(zhǔn)的強制類型轉(zhuǎn)換與之匹配,比如使用 printData(double data, int num),就可以將para的類型強制轉(zhuǎn)換為double類型。但是還有printData(int data, int num)和printData(long data, char num)這兩個函數(shù)可以強制轉(zhuǎn)換para。因此,C++將拒絕這種函數(shù)的調(diào)用,將這種調(diào)用視為錯誤。
重載函數(shù)通常用在同一個作用域內(nèi),用同一個函數(shù)名命名一組功能相似的函數(shù),這樣做減少了函數(shù)名的數(shù)量,提高了函數(shù)的通用性,避免了名字空間的污染,對于程序的可讀性有很大的好處。
三、非函數(shù)重載的情況
下面這種兩種情況不能視為函數(shù)重載:
int fun(int a); int fun(int &a);
從編譯器的角度出發(fā),參數(shù)a與參數(shù)列表原型int a和int &a都匹配,編譯器無法確定使用哪個函數(shù),為避免這種混亂,編譯器在檢查參數(shù)類型時將把類型本身和類型引用看作是同一個特征類型。
int fun(int a, float b); double fun(int a, float b);
C++不允許這樣的方式重載函數(shù),雖然返回值可以不一樣,但是參數(shù)列表必須不一樣。
四、函數(shù)重載的使用原則
(1)、僅當(dāng)函數(shù)的基本功能比較相近,但是需要使用不同形式的參數(shù)實現(xiàn)功能時才應(yīng)該使用函數(shù)重載,盡量不要用同一函數(shù)名去實現(xiàn)完全不相干的功能;
(2)、在同一個作用范圍內(nèi)使用函數(shù)重載,同一個范圍即:同一個命名空間或者同一個類等;
(3)、重載函數(shù)的名稱必須相同,函數(shù)的參數(shù)列表須不相同,即參數(shù)列表中參數(shù)的類型,參數(shù)的個數(shù)或參數(shù)的順序不相同;
(4)、重載函數(shù)可以有相同的返回值類型或者不同的返回值類型,反之僅僅是返回類型不同不足以作為函數(shù)的重載。
五、FAQ
1、C++中對函數(shù)重載是如何處理的?
在.cpp文件中,雖然兩個函數(shù)的函數(shù)名一樣,但是,C++編譯器在內(nèi)部使用“名稱修飾”或“名稱矯正”轉(zhuǎn)換,它根據(jù)函數(shù)中參數(shù)列表的區(qū)別為每個函數(shù)進行加密 ,例如:
int fun(int a, float b)和double fun(int a, float b)
編譯器在內(nèi)部可以轉(zhuǎn)換為:
?fun@@YAHHH@Z和?fun@@YAMMM@Z
"?"表示名稱開始,"?"后邊是函數(shù)名;“@@YA”表示參數(shù)表開始,后邊的3個字符分別表示返回值類型,兩個參數(shù)類型;“@Z”表示名稱結(jié)束。
由于在.cpp文件中,兩個函數(shù)生成的符號表中字符的名稱不一樣,所以是可以編譯通過的。
2、C語言中為什么不能支持函數(shù)重載?
編譯器在編譯.c文件時,只會給函數(shù)進行簡單的重命名。具體的方法是給函數(shù)名之前加上"_”;所以編譯前兩個函數(shù)名相同的函數(shù)在編譯之后的函數(shù)名也照樣相同;因此調(diào)用時會因為不知道到底調(diào)用哪個而出錯。
int fun(int a, float b)和double fun(int a, float b)
編譯器在內(nèi)部都轉(zhuǎn)換為:_fun,無法區(qū)分,
只有不同的函數(shù)名字int fun1(int a, float b)和double fun2(int a, float b)
編譯器在內(nèi)部轉(zhuǎn)換為:_fun1和_fun2,這才能區(qū)分開來。
以上就是C++重載的奧義之函數(shù)重載詳解的詳細內(nèi)容,更多關(guān)于C++函數(shù)重載的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺析VSCode launch.json中的各種替換變量的意思 ${workspaceFolder} ${file} $
這篇文章主要介紹了VSCode launch.json中的各種替換變量的意思 ${workspaceFolder} ${file} ${fileBasename} ${fileDirname}等,非常不錯具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03C語言數(shù)據(jù)結(jié)構(gòu)之判斷循環(huán)鏈表空與滿
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之判斷循環(huán)鏈表空與滿的相關(guān)資料,希望通過本文能幫助到大家,讓大家掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10解析VC中創(chuàng)建DLL,導(dǎo)出全局變量,函數(shù)和類的深入分析
本篇文章是對VC中創(chuàng)建DLL,導(dǎo)出全局變量,函數(shù)和類進行了詳細的分析介紹,需要的朋友參考下2013-05-05