C++超詳細(xì)分析函數(shù)重載的使用_第1頁
C++超詳細(xì)分析函數(shù)重載的使用_第2頁
C++超詳細(xì)分析函數(shù)重載的使用_第3頁
C++超詳細(xì)分析函數(shù)重載的使用_第4頁
C++超詳細(xì)分析函數(shù)重載的使用_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第C++超詳細(xì)分析函數(shù)重載的使用目錄一、函數(shù)重載分析(上)1.1重載的定義1.2函數(shù)重載的定義1.3函數(shù)重載需要滿足的條件1.4編譯器調(diào)用重載函數(shù)的準(zhǔn)則1.5函數(shù)重載的注意事項1.6小結(jié)二、函數(shù)重載分析(下)2.1函數(shù)重載遇上函數(shù)指針2.2C++和C的相互調(diào)用2.3使得C代碼只會以C的方式被編譯的解決方案2.4小結(jié)

一、函數(shù)重載分析(上)

1.1重載的定義

定義:同一個標(biāo)識符在不同的上下文有不同的意義

1.2函數(shù)重載的定義

用同一個函數(shù)名定義不同的函數(shù)當(dāng)函數(shù)名和不同的參數(shù)搭配時函數(shù)的含義不同

如下:

下面看一段代碼,感受一下:

#includestdio.h

#includestring.h

intfunc(intx)

returnx;

intfunc(inta,intb)

returna+b;

intfunc(constchar*s)

returnstrlen(s);

intmain(intargc,char*argv[])

printf("%d\n",func(3));

printf("%d\n",func(4,5));

printf("%d\n",func("D.T.Software"));

return0;

}

下面為輸出結(jié)果:

1.3函數(shù)重載需要滿足的條件

函數(shù)重載至少滿足下面的一個條件:

參數(shù)個數(shù)不同參數(shù)類型不同參數(shù)順序不同

下圖所示就是參數(shù)的順序不同:

下面看一個函數(shù)默認(rèn)參數(shù)遇上函數(shù)重載的實例程序:

#includestdio.h

intfunc(inta,intb,intc=0)

returna*b*c;

intfunc(inta,intb)

returna+b;

intmain(intargc,char*argv[])

intc=func(1,2);

return0;

}

下面為輸出結(jié)果:

編譯報錯,因為模棱兩可。如果說調(diào)用第一個函數(shù)說的過去,因為符合函數(shù)默認(rèn)參數(shù)規(guī)則,c的值已經(jīng)確定;調(diào)用第二個函數(shù)也符合常理,所以編譯不會通過。

1.4編譯器調(diào)用重載函數(shù)的準(zhǔn)則

將所有同名函數(shù)作為候選者

嘗試尋找可行的候選函數(shù)

精確匹配實參通過默認(rèn)參數(shù)能夠匹配實參通過默認(rèn)類型轉(zhuǎn)換匹配實參

匹配失敗

最終尋找到的候選函數(shù)不唯一,則出現(xiàn)二義性,編譯失敗。無法匹配所有候選者,函數(shù)未定義,編譯失敗。

1.5函數(shù)重載的注意事項

重載函數(shù)在本質(zhì)上是相互獨立的不同函數(shù)重載函數(shù)的函數(shù)類型不同函數(shù)返回值不能作為函數(shù)重載的依據(jù)

函數(shù)重載是由函數(shù)名和參數(shù)列表決定的!?。?/p>

函數(shù)重載的本質(zhì)是什么?下面通過一段代碼深入分析,編譯環(huán)境為VS2012。

#include"stdafx.h"

#includestdio.h

intadd(inta,intb)//int(int,int)

returna+b;

intadd(inta,intb,intc)//int(int,int,int)

returna+b+c;

intmain()

printf("%p\n",(int(*)(int,int))add);

printf("%p\n",(int(*)(int,int,int))add);

return0;

}

由C語言的知識可以知道,函數(shù)名就是函數(shù)的入口地址,所以輸出結(jié)果如下:

可以看到,兩個add()函數(shù)的入口地址不一樣,所以這兩個add是兩個不同的函數(shù)。

編譯器是如何看待這兩個add()函數(shù)的呢?下面來深入分析。先看一下編譯器產(chǎn)生的中間結(jié)果,在Test-Debug-Test.obj文件中。

然后使用VS2012里面自帶的命令行工具查看Test.obj里面有什么東西。

上圖示為VS2012命令行所在位置

輸入dumpbin,如下:

這里只需要關(guān)系SYMBOLS(符號表),符號表就是編譯器在編譯過程中根據(jù)源代碼所生成的一張表,這張表有程序的函數(shù)名變量等等。

輸入以下命令,其中/symbols后面為Test.obj所在的位置。

找到下面的地方,可以看到編譯器編譯(int__cdecladd(int,int))時標(biāo)識符為add@@YAHHH@Z;而編譯器編譯(int__cdecladd(int,int,int))時標(biāo)識符為add@@YAHHHH@Z,也就是說編譯器在編譯這兩個函數(shù)時已經(jīng)把這兩個函數(shù)分別對待,盡管它們名字一樣,所以兩個add()函數(shù)的入口地址不一樣,這就很好理解了。

1.6小結(jié)

函數(shù)重載是C++中引入的概念函數(shù)重載用于模擬自然語言中的詞匯搭配函數(shù)重載使得C++具有更豐富的語義表達(dá)能力函數(shù)重載的本質(zhì)為相互獨立的不同函數(shù)C++中通過函數(shù)名和函數(shù)參數(shù)確定函數(shù)調(diào)用

二、函數(shù)重載分析(下)

2.1函數(shù)重載遇上函數(shù)指針

將重載函數(shù)名賦值給函數(shù)指針時

根據(jù)重載規(guī)則挑選與函數(shù)指針參數(shù)列表一致的候選者嚴(yán)格匹配候選者的函數(shù)類型與函數(shù)指針的函數(shù)類型

下面看一段代碼:

#includestdio.h

#includestring.h

intfunc(intx)

returnx;

intfunc(inta,intb)

returna+b;

intfunc(constchar*s)

returnstrlen(s);

typedefint(*PFUNC)(inta);

intmain(intargc,char*argv[])

intc=0;

PFUNCp=func;

c=p(1);

printf("c=%d\n",c);

return0;

}

下面為輸出結(jié)果:

這也就是前面說的通過函數(shù)指針?biāo)赶虻暮瘮?shù)類型參數(shù)列表來進(jìn)行選擇。

注意事項

函數(shù)重載必然發(fā)生在同一個作用域中編譯器需要用參數(shù)列表或函數(shù)類型進(jìn)行函數(shù)選擇無法直接通過函數(shù)名得到重載函數(shù)的入口地址(可以通過指針來獲取)

如下,這段代碼想通過函數(shù)名獲取重載函數(shù)的入口地址:

#includestdio.h

intadd(inta,intb)//int(int,int)

returna+b;

intadd(inta,intb,intc)//int(int,int,int)

returna+b+c;

intmain()

printf("%p\n",add);

printf("%p\n",add);

return0;

}

編譯的時候會報錯,無法確定是哪個函數(shù)。

2.2C++和C的相互調(diào)用

實際工程中C++和C代碼相互調(diào)用是不可避免的C++編譯器能夠兼容C語言的編譯方式C++編譯器會優(yōu)先使用C++編譯的方式extern關(guān)鍵字能強制讓C++編譯器進(jìn)行C方式的編譯

如下:

在Linux環(huán)境下新建一個9-2文件夾,先在文件夾下新建add.c和add.h文件,如下:

add.c:

#include"add.h"

intadd(inta,intb)

returna+b;

}

add.h:

intadd(inta,intb);

通過linux命令cd進(jìn)入9-2文件夾,再將add.c轉(zhuǎn)換成add.o文件,如下所示:

然后在9-2文件夾下建一個main.cpp文件,如下:

mian.cpp:

#includestdio.h

#include"add.h"

intmain()

intc=add(1,2);

printf("c=%d\n",c);

return0;

}

對程序進(jìn)行編譯,發(fā)現(xiàn)程序報錯,沒有定義add()函數(shù),但是函數(shù)確實已經(jīng)定義了,可以使用linux中的nm指令查看add.o里面的信息,打印出來的就是符號表信息,可以看到確實有add。

這個時候就需要使用extern關(guān)鍵字強制讓C++編譯器進(jìn)行C方式的編譯,所以main.cpp就要修改成這樣:

#includestdio.h

extern"C"

#include"add.h"

intmain()

intc=add(1,2);

printf("c=%d\n",c);

return0;

}

這樣編譯就能通過了:

如果在9-2文件中新建一個main.c文件,main.c里面的代碼與main.cpp中的相同。

進(jìn)行編譯,發(fā)現(xiàn)會報錯誤,因為extern關(guān)鍵詞寫法是C++中的,C語言不支持該寫法。那有沒有一種寫法既能被C語言編譯通過,又能讓C++編譯通過呢?且看下面。

2.3使得C代碼只會以C的方式被編譯的解決方案

_cplusplus是C++編譯器內(nèi)置的標(biāo)準(zhǔn)宏定義_cplusplus的意義是確保C代碼以統(tǒng)一的C方式被編譯成目標(biāo)文件

如下:

所以上述代碼可以寫作,main.c和main.cpp均為:

#includestdio.h

#ifdef__cplusplus

extern"C"{

#endif

#include"add.h"

#ifdef__cplusplus

#endif

intmain()

intc=add(1,2);

printf("c=%d\n",c);

return0;

}

這樣程序在C語言和C++的編譯環(huán)境下均能通過,如下:

注意事項

C++編譯器不能以C的方式編譯重載函數(shù)

編譯方式?jīng)Q定函數(shù)名被編譯后的目標(biāo)名

C++編譯方式將函數(shù)名和參數(shù)列表編譯成目標(biāo)名C編譯方式只將函數(shù)名作為目標(biāo)名進(jìn)行編譯

下面通過一個例子說明一下:

intadd(inta,intb)//int(int,int)

returna+b;

intadd(inta,intb,intc)//int(int,int,int)

returna+b+c;

}

將該代碼編譯成目標(biāo)文件,取名為test.oo,然后通過linux中的nm命令查看test.oo中的東西,可以看到test符號表里面有兩個東西T_Z3addii和T_Z3addiii,這就是add函數(shù)被編譯過后的目標(biāo)函數(shù)名,ii表示兩個參數(shù),iii表示三個參數(shù)。

如果采用C方式編譯重載函數(shù),代碼如下:

extern"C"

int

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論