在C原因中,一個(gè)函數(shù)不能與另一個(gè)函數(shù)重名,而在C++中,只要一個(gè)函數(shù)的參數(shù)列表與另一個(gè)函數(shù)的參數(shù)列表不完全相同,函數(shù)名就可以相同。而C++這一特點(diǎn)就是函數(shù)的重載。
同一個(gè)名字因?yàn)閰?shù)列表不同,展現(xiàn)了不同的結(jié)果,也叫靜多態(tài)。
①函數(shù)名相同,函數(shù)參數(shù)列表不同(類(lèi)型、個(gè)數(shù)、順序) ②匹配原則1:嚴(yán)格匹配,找到再調(diào)用 ③匹配原則2:通過(guò)隱式類(lèi)型轉(zhuǎn)換尋求一個(gè)匹配,找到則調(diào)用 ④返回值類(lèi)型不構(gòu)成重載條件
/*要是放在C語(yǔ)言中,這段代碼必然是編譯不通過(guò),而在C++中是合乎重載原則的*/#include <iostream>using namespace std;float abs(float i){ return (i >= 0 ? i : -i);}double abs(double i){ return (i >= 0 ? i : -i);}int abs(int i){ return (i >= 0 ? i : -i);}int main(){ /*abbiguous二義性*/ float i = abs(-5.5f);/*默認(rèn)調(diào)用第一個(gè)abs*/ float j = abs(-4.4);/*默認(rèn)調(diào)用第二個(gè),如果注銷(xiāo)掉第二個(gè)abs,編譯時(shí)出錯(cuò)報(bào)二義性錯(cuò)誤*/ cout << i << endl; cout << j << endl; /*浮點(diǎn)數(shù)默認(rèn)大小(類(lèi)型)*/ cout << "sizeof(4.5)=" << sizeof(4.5) << endl;/*default*/ cout << "sizeof(4.5f)=" << sizeof(4.5f) << endl; return 0;}注意: 重載時(shí)的二義性:如果計(jì)算機(jī)存在有兩種隱式轉(zhuǎn)換選擇,計(jì)算機(jī)不會(huì)去選,而報(bào)二義性錯(cuò)誤 eg1:double可以隱式轉(zhuǎn)換為float或int,如果abs(-4.4)并且定義float與int分別作為參數(shù)的ads(),編譯時(shí)則會(huì)產(chǎn)生二義性 eg2:double->int/float會(huì)產(chǎn)生兩義性,int->long/double也會(huì)產(chǎn)生兩義性。 即兩個(gè)特例重載時(shí)需要注意。 為了避免重載中的二義性問(wèn)題,使用時(shí)按所需強(qiáng)制轉(zhuǎn)換,不要讓計(jì)算機(jī)去自己選擇
對(duì)于下面這段程序來(lái)說(shuō):
#include <iostream>using namespace std;//不設(shè)置,C++編譯器默認(rèn)傾軋void func(int a){cout<<"a = "<<a<<endl;}void func(char a){cout<<"a = "<<a<<endl;}void func(int a, char b){cout<<"a = "<<a<<endl<<"b = "<<b<<endl;}void func(char a, int b){cout<<"a = "<<a<<endl<<"b = "<<b<<endl;}int main(void){ int a = 10; char b = 'b'; func(a); func(b); func(a,b); func(b,a); return 0;}上面的程序在經(jīng)過(guò)C++編譯器編譯時(shí)就類(lèi)似于變成了下面這種寫(xiě)法,這種寫(xiě)法與其重載函數(shù)名以及參數(shù)類(lèi)型有關(guān):
#include <iostream>using namespace std;/*定義自動(dòng)傾軋*/void func_i(int a){cout<<"a = "<<a<<endl;}void func_c(char a){cout<<"a = "<<a<<endl;}void func_ic(int a, char b){cout<<"a = "<<a<<endl<<"b = "<<b<<endl;}void func_ci(char a, int b){cout<<"a = "<<a<<endl<<"b = "<<b<<endl;}int main(void){ int a = 10; char b = 'b'; /*調(diào)用也自動(dòng)傾軋*/ func_i(a); func_c(b); func_ic(a,b); func_ci(b,a); return 0;}在C++中,定義階段與聲明操作階段均會(huì)進(jìn)行傾軋(編譯時(shí)傾軋),使用extern “C”,可以將某函數(shù)設(shè)置為不傾軋,可C++需要傾軋以支持重載,為什么弄一個(gè)不傾軋出來(lái)呢?
分析: 首先,函數(shù)聲明時(shí)與定義時(shí)要么都傾軋,要么都不傾軋,必須得一一對(duì)應(yīng),否則會(huì)報(bào)函數(shù)找不到的錯(cuò)誤。傾軋是編譯時(shí)進(jìn)行的,而對(duì)于C++要兼容C的問(wèn)題,C++就必須兼容C的語(yǔ)法與C庫(kù)(鏈接庫(kù)),C庫(kù)只在連鏈接時(shí)加入,不存在讓C++編譯器去傾軋的問(wèn)題;而C頭文件中聲明的C庫(kù)函數(shù)在調(diào)用時(shí)會(huì)傾軋,要想使用不參加傾軋的C庫(kù)函數(shù),C++中編譯時(shí)就不能傾軋C的頭文件中對(duì)于庫(kù)函數(shù)的聲明,即C庫(kù)中已經(jīng)不能修改不傾軋為傾軋,則必須將頭文件中的聲明也設(shè)置為不傾軋,以此與庫(kù)中相互對(duì)應(yīng)。如果查看C的標(biāo)準(zhǔn)頭文件,可以發(fā)現(xiàn)其中有一個(gè)extern “C”,表示不傾軋C的函數(shù)聲明。如下是string.h頭文件中的一部分:
/*查看string.h,發(fā)現(xiàn)在函數(shù)聲明之前,就對(duì)C++編譯器的編譯方式進(jìn)行聲明extern "C",即聲明為:C++編譯器在編譯時(shí)不傾軋*/#ifndef _INC_STRING#define _INC_STRING#ifdef __cplusplus //如果是C++編譯器就要進(jìn)行不傾軋?jiān)O(shè)置extern "C" {#endif... //函數(shù)聲明等#ifdef __cplusplus//與上面匹配}#endif...分別查看不同集成承環(huán)境中的string.h文件,都是有對(duì)函數(shù)的extern “C”不傾軋限定:

舉例說(shuō)明:
#include <iostream>#include <string.h>using namespace std;extern "C"{ void func(int a){cout<<"a = "<<a<<endl;}}int main(void){ int a = 10; func(a); return 0;}由于定義時(shí)不傾軋,而調(diào)用時(shí)傾軋,經(jīng)過(guò)C++編譯器,其代碼成為:
#include <iostream>using namespace std;/*定義時(shí)設(shè)置成不傾軋,在編譯時(shí),其函數(shù)名依舊相同*/void func(int a){cout<<"a = "<<a<<endl;}int main(void){ int a = 10; /*經(jīng)C++編譯器,函數(shù)名變?yōu)閮A軋后的函數(shù)名*/ func_i(a); return 0;}這樣的代碼是不能夠完成編譯的。而要上面的函數(shù)能夠正常調(diào)用,要么定義與調(diào)用時(shí)均遵循默認(rèn)的傾軋,要么均設(shè)置為不傾軋,做法如下:
/*main.cpp*/#include<iostream>#include"func.h"using namespace std;int main(void){ int a = 10; func(a); return 0;}/*func.c*/#include<iostream>using namespace std;extern "C"{ void func(int a){cout<<"a = "<<a<<endl;}}/*func.h*/#ifndef FUNC_H_#define FUNC_H_extern "C" void func(int);//聲明為不傾軋,調(diào)用根據(jù)聲明調(diào)用,自然不傾軋#endif將函數(shù)聲明與函數(shù)定義時(shí),都設(shè)置為不傾軋即可。當(dāng)然均不設(shè)置,采用默認(rèn)也是可以編譯通過(guò)的。但是聲明與定義兩部分只要任意一個(gè)設(shè)置為傾軋,另一個(gè)設(shè)置為不傾軋,編譯就不能通過(guò)。
測(cè)試結(jié)果如下:
聲明中不加extern “C”,編譯出錯(cuò):
聲明中加extern “C”,編譯不出錯(cuò): 
總之一句話,傾軋是C++為了實(shí)現(xiàn)函數(shù)重載而設(shè)計(jì)的,不傾軋的extern “C”則是為了兼容C而后實(shí)現(xiàn)的。我們編程一般犯不著對(duì)自定義的C++函數(shù)設(shè)置。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注