C++對象模型、多態以及單一繼承下的運行內存分析

引言

對中高級程序員來說,C++內存模型是C++知識點裏比較重要的一部分,對此瞭解之後便可對C++類的實現機制以及多態性有更多的理解,尤其是C++運行過程中各個對象在內存裏的分佈情況,以下對這些知識點做簡要介紹。

C++類的構成:

C++的類由兩部分構成,類裏的數據和類裏的函數,類數據有兩種,靜態的非靜態的,類函數有三種,靜態的非靜態的,virtual的

對象模型

不同的對象模型會造成佈局和存取時間上的負擔,下面主要介紹三種模型

  1. 簡單對象模型,每一個類由一系列slots構成,每一個slots指向每一個類成員(每一個數據成員和函數成員),每個類成員按聲明順序制定一個slots,但是類成員本身並不放在類裏面,類裏面只存放指向類成員的指針,這樣可以解決不同類型的成員所需要的不同的存儲空間的問題,此外,成員是以類中slot的索引值來尋址的, 如下圖所示:
  2. 表格驅動對象模型,把類成員相關的信息抽出來,分別放在數據成員表和函數成員表裏面,類本身含有指向這兩個表的指針,數據成員表裏包含數據本身,而函數成員表裏面類似於簡單對象模型,裏面由一系列slots構成,每一個slots指向每一個成員,如圖:
  3. C++對象模型,由簡單對象模型派生而來,並對內存存儲空間和存取時間做了優化。在此數據模型裏面,非靜態數據成員放在類裏面,靜態數據成員放在類外面,類的成員函數則均放在類外面,虛函數由以下兩個步驟實現:
     (1)虛函數表 virtual table,每個類會產生一堆指向虛函數的指針,這些指針被統一放在一個表格中,這個表則即虛函數表

     (2)虛表指針 vptr, 每個類會被安插一個指針,指向類的虛函數表,虛表指針 vptr的設定和重置由類的構造、析構、賦值構
        造函數運算符自動完成,每個類所關聯的類型信息type_info object也由虛函數表指出,通常放在虛函數表的第一個slot.

C++對象模型以實際類舉例,如下所示:

C++虛繼承

虛繼承是指繼承由virtual修飾,具體形式如下所示:

class derived : virtual public base
{
}

在虛繼承情況下,base類不管在繼承結構中被派生了多少次,永遠只會存在一個實例

C++多態

C++中有3種方式支持多態

經由一組隱式的裝換操作來實現,即把子類對象賦值給基類指針;
通過虛函數機制,在執行期間確定調用子類的某個行爲;
通過dynamic_cast和typeid運算符,dynamic_cast用於執行繼承體系中安全的向下轉型

C++類所需存儲內存

一個類所需要的內存主要包括

類中非靜態數據成員所佔總內存的大小;
由於alignment需求而填補上去的空間;
爲了支持virtual而由內部產生的額外負擔。

C++單一繼承情況下的運行內存佈局

  在單一繼承的結構下,其運行內存佈局如下所示

注意當基類直接被初始化爲子類時,子類就會被切割,然後塞入基類大小的內存中,而子類的特性就會消失,也就不會有多態。

總結

 瞭解C++模型之後可以對虛函數,虛繼承,虛接口,有更進一步的認識,可以在C++編程模型中對效率和空間有更深刻的理解,從而可以進一步合理的使用C++中的各種語法。

參考:

深入探索C++對象模型第一章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章