c++函数重载机制实现原理
原文鏈接:https://blog.csdn.net/gogogo_sky/article/details/72807123
一、c++函數(shù)重載的定義:
在同一作用域類,一組函數(shù)的函數(shù)名相同,參數(shù)列表不同(參數(shù)個(gè)數(shù)不同/參數(shù)類型不同),返回值可同可不同
二、函數(shù)重載的作用:
重載函數(shù)通常用來(lái)在同一個(gè)作用域內(nèi)?用同一個(gè)函數(shù)名 命名一組功能相似的函數(shù),這樣做減少了函數(shù)名的數(shù)量,避免了名字空間的污染,對(duì)于程序的可讀性有很大的好處。
三、函數(shù)重載是一種靜態(tài)多態(tài):
(1)多態(tài):用同一個(gè)東西表示不同的形態(tài);?
(2)多態(tài)分為:?
靜態(tài)多態(tài)(編譯時(shí)的多態(tài))?
動(dòng)態(tài)多態(tài)(運(yùn)行時(shí)的多態(tài));?
(3)函數(shù)重載是一種靜態(tài)多態(tài);
四、c++函數(shù)重載的原理:
(一)?
編譯器在編譯.cpp文件中當(dāng)前使用的作用域里的同名函數(shù)時(shí),根據(jù)函數(shù)形參的類型和順序會(huì)對(duì)函數(shù)進(jìn)行重命名(不同的編譯器在編譯時(shí)對(duì)函數(shù)的重命名標(biāo)準(zhǔn)不一樣)但是總的來(lái)說(shuō),他們都把文件中的同一個(gè)函數(shù)名進(jìn)行了重命名;
- 在vs編譯器中:?
根據(jù)返回值類型(不起決定性作用)+形參類型和順序(起決定性作用)的規(guī)則重命名并記錄在map文件中。 - 在linux g++ 編譯器中:?
根據(jù)函數(shù)名字的字符數(shù)+形參類型和順序的規(guī)則重命名記錄在符號(hào)表中;從而產(chǎn)生不同的函數(shù)名,當(dāng)外面的函數(shù)被調(diào)用時(shí),便是根據(jù)這個(gè)記錄的結(jié)果去尋找符合要求的函數(shù)名,進(jìn)行調(diào)用;
五、為什么c語(yǔ)言不能實(shí)現(xiàn)函數(shù)重載
編譯器在編譯.c文件時(shí),只會(huì)給函數(shù)進(jìn)行簡(jiǎn)單的重命名;具體的方法是給函數(shù)名之前加上”_”;所以加入兩個(gè)函數(shù)名相同的函數(shù)在編譯之后的函數(shù)名也照樣相同;調(diào)用者會(huì)因?yàn)椴恢赖降渍{(diào)用那個(gè)而出錯(cuò);
六、實(shí)驗(yàn)說(shuō)明:
(一)在C語(yǔ)言中,如果兩個(gè)函數(shù)的函數(shù)名相同,不管形參和返回值是否相同,程序運(yùn)行都會(huì)發(fā)生錯(cuò)誤?
在.c文件中;寫出下列代碼,在vs2008運(yùn)行出錯(cuò):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
運(yùn)行結(jié)果:報(bào)錯(cuò)—函數(shù)“int Add(int,int)”已有主體?
錯(cuò)誤原因:?
程序從編譯到運(yùn)行出結(jié)果幾個(gè)階段。其中一個(gè)階段提到生成符號(hào)表。?
我們來(lái)看一下上邊的函數(shù)成的符號(hào)表。符號(hào)表是在.map文件里,在vs里默認(rèn)不顯示符號(hào)表文件。要想顯示出來(lái),這樣設(shè)置:?
工程名右擊—>屬性—->配置屬性—->鏈接器—–>調(diào)試—->生成映射文件—>選擇是;?
上邊寫有兩個(gè)同名函數(shù)的c程序中根本編譯不通過(guò)(報(bào)錯(cuò):Add函數(shù)已有主體)就無(wú)法生成符號(hào)表。所以,我去掉一個(gè)函數(shù),讓程序編譯通過(guò),看看函數(shù)名在符號(hào)表中的命名?
通過(guò)這個(gè)我們可以得出,c程序中的Add()函數(shù)在符號(hào)表中的重命名就是函數(shù)名前邊加個(gè)下劃線。所以如果一個(gè)c程序中出現(xiàn)了同名函數(shù),他們?cè)诜?hào)表中的命名一樣,這樣調(diào)用時(shí)就出現(xiàn)了沖突。
(二)將上面的代碼在改為.cpp文件,編譯之后在map中查看兩個(gè)Add()函數(shù)的名字;?
這里我們可以看出,在.cpp文件中,雖然兩個(gè)函數(shù)的函數(shù)名一樣,但是他們?cè)诜?hào)表中生成的名稱不一樣。?
‘?’表示名稱開(kāi)始,‘?’后邊是函數(shù)名“@@YA”表示參數(shù)表開(kāi)始,后邊的3個(gè)字符分別表示返回值類型,兩個(gè)參數(shù)類型。“@Z”表示名稱結(jié)束。?
由于在.cpp文件中,兩個(gè)函數(shù)生成的符號(hào)表中的名稱不一樣,所以是可以編譯通過(guò)的。
那么既然c++編譯器和c編譯器對(duì)函數(shù)名的重命名規(guī)則不一樣;?
那么怎么在一個(gè).cpp文件中調(diào)用.c文件的函數(shù)??
以前寫的一篇相關(guān)文章?
(三)不同的編譯器對(duì)c++代碼的函數(shù)重命名規(guī)則不一樣;?
下面看看在linux下g++編譯器對(duì)相同代碼函數(shù)名的重命名;
cpp文件在linux虛擬機(jī)里需要用g++編譯。?
安裝g++很簡(jiǎn)單。命令: yum install gcc gcc-c++?
安裝好了之后就可以了。運(yùn)行程序之后,使用命令:objdump a.out -t > test.out?
-t是表示生成符號(hào)表,最后是將生成的符號(hào)表用重定向符號(hào)放在test.out文件。打開(kāi)test.out文件,就會(huì)發(fā)現(xiàn),整形數(shù)相加的函數(shù)Add(int a,int b)生成的符號(hào)表中,Add函數(shù)名被記錄為_Z3Addiii,其中。_Z表示符號(hào)表名稱開(kāi)始,?3代表函數(shù)名的字符個(gè)數(shù),iii代表按順序三個(gè)形參的類型;?
可以看出:同樣的.cpp文件在window的vs2008編譯器和linux的g++編譯中,相同的函數(shù)名進(jìn)過(guò)編譯之后的重新命名不一樣;
總結(jié)
以上是生活随笔為你收集整理的c++函数重载机制实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C++中“引用”的底层实现
- 下一篇: C++中的friend详细解析