何為C++物件模型?
C++物件模型可以概括為以下2部分:
1. 語言中直接支援物件導向程式設計的部分
2. 對於各種支援的底層實現機制
引言
現在有一個Point類,聲明如下:
class Point { public: Point(float xval); virtual ~Point(); float x() const; static int PointCount(); protected: virtual ostream& print(ostream &os) const; float _x; static int _point_count;};
這個類在機器上是通過什麼模型來表示的呢?下面就介紹三種不同的實現方式。
1. 簡單物件模型
簡單物件模型名副其實,十分簡單。在簡單物件模型中,一個 object是由一系列slots組成,每個slot相當於一個指標,指向一個member,memebers按照聲明的順序與slots一一對應,這裡的members包括data members和function members。
如果將簡單物件模型應用在Point Class上,結構圖如下:
優點:十分簡單,降低了編譯器設計的複雜度。
缺點:空間和時間上的效率降低。由於所有member都對應一個slot指標,所以每個object在空間上額外多出:member's number 乘以指標大小的空間。同時由於訪問object的每個member都需要一次slot的額外索引,所以在時間的效率也會降低。
2. 表格驅動物件模型
表格驅動物件模型將member data和member function分別映射成兩個表格member data table和function member table,而object本身只儲存指向這兩個表格的指標。 其中function member table是由一系列的slot組成,每個slot指向一個member function; member data table則直接儲存的member data本身。如果將表格驅動物件模型應用在Point Class上,結構圖如下:
優點:採用兩層索引機制,對object變化提供比較好的彈性,在object的nonstatic data member有所改變時,而應用程式代碼沒有改變,這時是不需要重新編譯的。
缺點:空間和時間上的效率降低,具體原因可以參考簡單物件模型的缺點分析。
3. C++ 物件模型
Stroustrup 早期設計的C++物件模型是從簡單物件模型改進而來的,並對記憶體空間和存取時間進行了最佳化。主要是將nonstatic data members儲存在每一個object中,而static data members以及所有的function members被隔離儲存區 (Isolated Storage)在所有object之外。
對虛函數的支援主要通過以下幾點完成的:
所有包含虛函數或者繼承自有虛函數基類的class都會有一個virtual table,該虛函數表格儲存體著一堆指向該類所包含的虛函數的指標。
每個class所關聯的type_info object也是由virtual table儲存的,一般會存在該表格的首個slot,type_info用於支援runtime type identification (RTTI)。
如果將C++物件模型應用在Point Class上,結構圖如下:
優點:空間和存取效率高,所有static data members以及所有的function members被隔離儲存區 (Isolated Storage)在所有object之外,可以減少每個object的大小,而nonstatic data members儲存在每一個object中,又提升了存取效率。
缺點:如果應用程式的代碼未曾更改,但所用到的class的nonstatic data members有所更改,那麼那些代碼仍然需要全部重新編譯,而前面的表格驅動模型在這方面提供了較大的彈性,因為他多提供了一層間接性,當然是付出了時間和空間上的代價。
在加上繼承情況下的物件模型
C++支援單繼承、多繼承、虛繼承,下面來看下base class實體在derived class中是如何被構建的。
簡單物件模型中可以通過derived class object中的一個slot來儲存base class subobject的地址,這樣就可以通過該slot來訪問base class的成員。這種實現方式的主要缺點是:因為間接性的儲存而導致空間和存取時間上存在額外負擔;優點是:derived class的結構不會因為base class的改變而改變。
表格驅動物件模型中可以利用一個類似base class table的表格來儲存所有基類的資訊。該表格中儲存一系列slot,每個slot儲存一個base class的地址。這種實現方式的缺點是:因為間接性的儲存而導致空間和存取時間上存在額外負擔;優點是:一是所有繼承的class都有一致的表現形式(包含一個base table指標,指向基類表)與基類的大小和數目沒有關係,二是base class table增加了子類的擴充性,當基類發生改變時,可以通過擴充、縮小或者更改base class table來進行調整。
以上兩種實現方式都存在一個重要的問題,就是由於間接性而導致的空間和時間上的額外負擔,並且該間接性的級數會隨著繼承的深度而增加。
C++ 最初採用的繼承模型並不採用任何間接性,所有基類的資料直接儲存在子類當中,這樣在儲存結構和訪問效率上是最高效的。當然也有缺點:當base class members有任何改變,用到此base class或者derived class的對象必須重新編譯。在C++ 2.0引入了virtual base class,需要一些間接性的方式來支援該特性,一般會匯入一個virtual base class table或者擴充已有的virtual table。
總結
以上就是深入研究C++的物件模型的全部內容,希望本文的內容對大家有所協助。