2017-06-23 42 views
1

我知道,只有一個每個成員函數的實例在內存中,該類的每一個對象使用它的存在繼承和壓倒一切的,但你能幫助我瞭解如何非虛擬的和虛擬的繼承和覆蓋的工作是通過解釋它在低級別上如何實現,以及如何在內存中進行解釋來實現的。底層處理非虛,虛,純虛的C++

+1

試試看書清單:https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list –

+0

沒有指定它,所以你的問題是無法回答的。但是請參閱[Stanley Lippman,* C++對象模型內部*。](http://rads.stackoverflow.com/amzn/click/0201834545) – EJP

回答

0

我不知道,有容易獲得該級別的大量信息。 C++標準傾向於避免這種實現細節。我知道的最好的書是Stan Lippman的「Inside the C++ Object Model」。這是相當古老的,但基本面可能仍然有效。

+0

標準不會「傾向於避免」,它明確地讓那些作爲實現定義。這意味着信息是可用的,不在標準中,而在編譯器的技術文檔或源代碼中。 – spectras

0

如何繼承,虛和壓倒一切的實現是不是標準的一部分,每個編譯器就可以實現它以任何方式。

雖然,我ununderstanding,這裏通常被大多數編譯器所使用的一般原則:

  • 非虛繼承本質上是一個隱藏的組成:空間分配給兩者的基類和派生對象的附加數據,並列在內存中。
  • 虛擬方法使用vtable,這是一個在類級別定義的指針數組,每個類的實例都有一個指針指向的數組。該表包含指向虛擬方法的指針。
  • 當在派生類中重寫的虛擬方法,這類定義與重寫的函數修改的指針其新V表的版本。它的成員將指向指向這個新表的虛表。
  • 純虛函數一般由指針想通vtable中設定爲NULL_PTR(因此「= 0」)

當調用一個虛擬函數,編譯器實際上將跟隨指向虛表,在vtable中讀入被調用函數的函數指針,然後運行該函數。

爲了更好地理解這一原則的低一級的執行,你可以看看this article

事情變得有多重繼承更加複雜,因爲數據獲得移動存儲:

  • 隨着非虛擬繼承,每個父類在派生類的附加數據之前並列在內存中,就像單個繼承一樣。但是,這意味着,當向上鑄造派生類型到其基礎類型之一,則編譯器將這個存儲器中,使得派生類型的適當部分被複制或指向。
  • 當使用虛擬繼承時,內存中的佈局幾乎相同,但在派生類中創建了一個vtable,其中包含基類的偏移量(請參閱this answer)。上傳時,編譯器將使用此值查找要複製或指向的內存的適當部分。
+0

當你對這個問題沒有足夠的自信時,請不要寫不準確的答案,它只會混淆提問者。 (儘管他們確實得到了總體思路,但是所有4個要點在某種程度上都是不正確的) – spectras