C++類的底層實現機制

我們首先從一個問題來闡明類的底層機理:

假如有一個類A笆包。里面有一個成員函數get(),比如:

A的頭文件

? ? ? ? 定義A a; 那么a.get()表示什么呢抛猖?首先給出答案是get(&a),由于在類的底層機制中谴分,成員函數的第一個參數都是一個指向該類數據結構的指針(靜態(tài)成員函數除外),所以成員函數get()的存在形式為void get(A* this);這也能說明為什么我們在成員函數的定義中總是能夠用this來指代調用對象逞带。

????????我們知道陌兑,要使用一個C++類铡原。必要的條件是在編譯期能得到這個類的頭文件偷厦,并在鏈接期能夠找到相應的符號的鏈接地址(比方成員函數、靜態(tài)數據成員等)燕刻。假設這個C++類與你的使用者在同一個project沪哺。那這個條件非常好滿足:

????????首先。C++類的頭文件非常好獲得酌儒。直接在使用者那里將類的頭文件include就可以辜妓。

????????其次,C++類往往被編譯器作為一個編譯單元,生成一個obj文件籍滴。

????????在最后進行鏈接的過程中酪夷,鏈接器會把project中全部的obj鏈接以生成終于的二進制目標文件。所以鏈接器在遇到一處對類成員函數(或其他形式的符號引用)時孽惰,會在這個類生成的obj文件里找到符號的鏈接地址晚岭。

????????那么,在代碼中使用一個C++類勋功,編譯期和鏈接期須要的究竟是些什么東西呢坦报?換句話說。滿足了什么樣的條件狂鞋。編譯器和鏈接器就不會抱怨了呢片择?依據C++語言的定義。一個C++類實際上是聲明或定義了例如以下幾類內容:

????????1.聲明了一個數據結構骚揍。類中的非靜態(tài)數據成員字管; 和代碼中看不到但假設有虛函數就會生成的虛表入口地址指針等。

????????2.聲明并定義了一堆函數信不,它們第一個參數都是一個指向這個數據結構的指針嘲叔。這些實際上就是類中那些非靜態(tài)成員函數(包含虛函數),它們盡管在類聲明中是寫在類的一對大括號內部抽活。但實際上沒有什么東西被加到前面第1條中所說的內部數據結構中硫戈。實際上。這種聲明僅僅是為這些函數添加了兩個屬性:函數名標識符的作用域被限制在類中下硕;函數第一個參數是this丁逝,被省略不寫了。

????????3.聲明并定義了還有一堆靜態(tài)函數卵牍。它們看上去就是一些普通函數果港,與這個類差點兒沒有關系沦泌。這些實際上就是類中那些靜態(tài)函數糊昙。它們也是一樣,不會在第1條中所說的內部數據結構中添加什么東西谢谦,僅僅是函數名標識符的作用域被限制在類中释牺。

????????4.聲明并定義了一堆全局變量。這些實際上就是類中那些靜態(tài)數據成員回挽。

????????5.聲明并定義了一個全局變量没咙。此全局變量是一個函數指針數組,用來保存此類中全部的虛函數的入口地址千劈。當然祭刚,這個全局變量生成的前提是這個類有虛函數。

看以下的一個樣例:

MyClass

對于上面列出的這個類MyClass,C++編譯器多數會以例如以下的方式進行編譯:

編譯結構

如今我們再來看一下為什么編譯器須要頭文件和符號地址就能夠編譯鏈接一個使用MyClass的程序了涡驮。

????????首先暗甥,因為編譯器須要在編譯期就知道類的內存布局,以保證能夠生成正確的開辟內存的代碼捉捅。及sizeof(MyClass)的值撤防。有了頭文件,編譯器就知道棒口,一個MyClass占用12字節(jié)的內存空間(見上圖寄月,兩個整數和一個指針)。

????????其次无牵,在調用MyClass的成員函數漾肮、靜態(tài)函數時,鏈接器須要知道這些函數的入口地址合敦,假設無法提供入口地址初橘,鏈接器就會報錯。

????????最后充岛。在引用MyClass的靜態(tài)數據成員時保檐,實際上與引用一個外部全局對象一樣,鏈接器須要知道這些變量的地址崔梗。假設無法提供這些變量的地址夜只,鏈接器也會報錯。

能夠看出:

1.?編譯期:必需要提供的是類的頭文件蒜魄,以使編譯器能夠得知類實例的尺寸和內存布局扔亥。

2.?鏈接期:必需要提供的是程序中引用過的,類的成員函數谈为、靜態(tài)函數旅挤、靜態(tài)數據成員的地址。以使鏈接器能夠正確的生成終于程序伞鲫。

????到這里粘茄,我們能夠猜到。實際上秕脓。導出一個類柒瓣。編譯器實際上僅僅須要將這個類中的:成員函數、靜態(tài)函數吠架、靜態(tài)數據成員當成普通的函數芙贫、全局變量導出就可以。也就是說傍药。我們實際上沒有“導出一個類”磺平。而是把這個類中須要被引用的“有定義的實體”的入口地址像普通函數和變量那樣正常導出就可以魂仍。因為里面的純虛函數VBar沒有定義,所以不會被導出拣挪。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末蓄诽,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子媒吗,更是在濱河造成了極大的恐慌仑氛,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闸英,死亡現場離奇詭異锯岖,居然都是意外死亡,警方通過查閱死者的電腦和手機甫何,發(fā)現死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門出吹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辙喂,你說我怎么就攤上這事捶牢。” “怎么了巍耗?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵秋麸,是天一觀的道長。 經常有香客問我炬太,道長灸蟆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任亲族,我火速辦了婚禮炒考,結果婚禮上,老公的妹妹穿的比我還像新娘霎迫。我一直安慰自己斋枢,他們只是感情好,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布知给。 她就那樣靜靜地躺著瓤帚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炼鞠。 梳的紋絲不亂的頭發(fā)上缘滥,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天轰胁,我揣著相機與錄音谒主,去河邊找鬼。 笑死赃阀,一個胖子當著我的面吹牛霎肯,可吹牛的內容都是我干的擎颖。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼观游,長吁一口氣:“原來是場噩夢啊……” “哼搂捧!你這毒婦竟也來了?” 一聲冷哼從身側響起懂缕,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤允跑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后搪柑,有當地人在樹林里發(fā)現了一具尸體聋丝,經...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年工碾,在試婚紗的時候發(fā)現自己被綠了弱睦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡渊额,死狀恐怖况木,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情旬迹,我是刑警寧澤火惊,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站奔垦,受9級特大地震影響矗晃,放射性物質發(fā)生泄漏。R本人自食惡果不足惜宴倍,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一张症、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸵贬,春花似錦俗他、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嗜浮,卻和暖如春羡亩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背危融。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工畏铆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吉殃。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓辞居,卻偏偏與公主長得像楷怒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瓦灶,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361