茂易網(wǎng)站建設(shè)鏈接購(gòu)買平臺(tái)
C++相較于C語(yǔ)言來(lái)說(shuō),重載是一重大特性,讓我們一起簡(jiǎn)單的回顧一下重載那些事
傳送門
- 函數(shù)重載是什么
- 為什么有函數(shù)重載
- 函數(shù)重載是如何實(shí)現(xiàn)的
- 總結(jié)
函數(shù)重載是什么
函數(shù)重載:是函數(shù)的一種特殊情況,C++允許在同一作用域中聲明幾個(gè)功能相似的同名函數(shù)
這些同名函數(shù)的形參列表(參數(shù)個(gè)數(shù)or類型or順序)必須不同
為什么有函數(shù)重載
通常用來(lái)處理功能類似數(shù)據(jù)類似的場(chǎng)景,簡(jiǎn)而言之,為方便使用.
或者說(shuō)發(fā)明C++的大佬們?cè)跊](méi)有C++使用C語(yǔ)言編程時(shí)日積月累的經(jīng)驗(yàn)吧()
函數(shù)重載是如何實(shí)現(xiàn)的
我們常說(shuō)C++是C語(yǔ)言的超集,是兼容C語(yǔ)言的一門高級(jí)編程語(yǔ)言.那我們有沒(méi)有想過(guò)這么一個(gè)問(wèn)題:為什么C++支持函數(shù)重載,而C語(yǔ)言不支持函數(shù)重載?
這也是寫這篇文章的目的所在
在C和C++中,應(yīng)該程序要運(yùn)行起來(lái),要經(jīng)歷:預(yù)處理、編譯、匯編、鏈接
下面我們借助Linux中g(shù)cc來(lái)理解一下這些過(guò)程
首先我們?cè)贚inux下創(chuàng)建以下文件
注: .cc也是cpp文件
這里采用了VScode遠(yuǎn)端連接的方法編輯(防止有人問(wèn)為什么不像vim或者nano)
Linux下,gcc是C語(yǔ)言的編譯器,g++是C++的編譯器
以下是一個(gè)簡(jiǎn)單的運(yùn)行方法(看不懂的家人可以跳過(guò),不是重點(diǎn))
首先
預(yù)處理的工作大致有 頭文件展開、宏替換、條件編譯、去掉注釋.
即代碼層面上的處理后,只保留需要執(zhí)行的部分.產(chǎn)生后綴為**.i**預(yù)處理文件.
編譯大致有檢查語(yǔ)法,生成匯編代碼.由**.i文件產(chǎn)生后綴為.s**匯編文件.
(像這樣)
匯編即把像上圖一樣的匯編代碼轉(zhuǎn)化成二進(jìn)制的機(jī)器碼供CPU讀取.由**.s文件生成.o**后綴的目標(biāo)文件.
鏈接找到調(diào)用函數(shù)的地址并鏈接對(duì)應(yīng),合并到一起
我們首先要大致明白,函數(shù)在調(diào)用時(shí),匯編代碼中都會(huì)有一個(gè)call指令來(lái)叫一下這個(gè)函數(shù)的地址
這里又牽扯到了符號(hào)表
鏈接時(shí)就會(huì)查詢符號(hào)表,符號(hào)表里記錄了函數(shù)與其地址的映射關(guān)系,即可以通過(guò)call地址的方式來(lái)找到函數(shù)并調(diào)用,但vs中的匯編代碼經(jīng)過(guò)修飾,展示并不直觀
我們借助Linux查看一下程序運(yùn)行產(chǎn)生的符號(hào)標(biāo)識(shí)
我們找到了一些特定標(biāo)識(shí),其實(shí)這些就可以看作是符號(hào)表內(nèi)函數(shù)地址與函數(shù)名,且與代碼對(duì)應(yīng).
我們仔細(xì)觀察可以發(fā)現(xiàn),每個(gè)函數(shù),嚴(yán)格一點(diǎn)我們稱之為重載函數(shù)之間地址是不相同的,他們的函數(shù)名也不相同.
他們的命名好像存在一種規(guī)則,有函數(shù)名的同時(shí)參數(shù)類型的首字符存在于函數(shù)名中!!!
每個(gè)平臺(tái)下規(guī)則不同,規(guī)則問(wèn)題不用糾結(jié)
至少在這里,是**_Z 函數(shù)名長(zhǎng)度 函數(shù)名 類型首字母**(指正類型會(huì)加一個(gè)i,如int* 即 ii)
這是不是意味著,重載函數(shù)的參數(shù)順序不同,類型不同,個(gè)數(shù)不同,就意味著編譯器底層會(huì)對(duì)其生產(chǎn)一個(gè)獨(dú)一無(wú)二的單獨(dú)的函數(shù)名和不同的地址,可以認(rèn)為從根本意義是他們不是同一個(gè)函數(shù)(可以這樣理解).
然后來(lái)觀察一下C語(yǔ)言
顯而易見(jiàn)的,底層并沒(méi)有對(duì)名稱進(jìn)行修飾!!!
C++的編譯器會(huì)將函數(shù)名在底層進(jìn)行修飾,形成獨(dú)一無(wú)二的名稱與地址,從而實(shí)現(xiàn)函數(shù)重載,但是C語(yǔ)言沒(méi)有.
所以C++支持函數(shù)重載,但C語(yǔ)言不支持.
從而引出了一個(gè)重要問(wèn)題:C語(yǔ)言和C++互相調(diào)用的鴻溝
編譯器底層將C++的函數(shù)名進(jìn)行了修飾,C語(yǔ)言在查詢符號(hào)表時(shí)找不到函數(shù).反之亦然
編譯器底層沒(méi)有將C語(yǔ)言的函數(shù)名進(jìn)行修飾,C++在查詢符號(hào)表時(shí)找不到函數(shù)
解決方法:extern “c”,通常借助宏判斷.
總結(jié)
淺談重載,希望能幫助大家對(duì)重載有更深的認(rèn)識(shí).
碼字不易,期待三連~~
有建議歡迎提出哦~~