深入理解C++的對象模型
何為C++對象模型?
C++對象模型可以概括為以下2部分:
1. 語言中直接支持面向?qū)ο蟪绦蛟O(shè)計的部分
2. 對于各種支持的底層實現(xiàn)機制
引言
現(xiàn)在有一個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; };
這個類在機器上是通過什么模型來表示的呢?下面就介紹三種不同的實現(xiàn)方式。
1. 簡單對象模型
簡單對象模型名副其實,十分簡單。在簡單對象模型中,一個 object
是由一系列slots
組成,每個slot
相當于一個指針,指向一個member
,memebers
按照聲明的順序與slots
一一對應(yīng),這里的members
包括data members
和function members
。
如果將簡單對象模型應(yīng)用在Point Class上,結(jié)構(gòu)圖如下:
優(yōu)點:十分簡單,降低了編譯器設(shè)計的復(fù)雜度。
缺點:空間和時間上的效率降低。由于所有member
都對應(yīng)一個slot
指針,所以每個object
在空間上額外多出:member's number
乘以指針大小的空間。同時由于訪問object
的每個member
都需要一次slot
的額外索引,所以在時間的效率也會降低。
2. 表格驅(qū)動對象模型
表格驅(qū)動對象模型將member data
和member function
分別映射成兩個表格member data table
和function member table
,而object
本身只存儲指向這兩個表格的指針。 其中function member table
是由一系列的slot組成,每個slot
指向一個member function
; member data table
則直接存儲的member data
本身。如果將表格驅(qū)動對象模型應(yīng)用在Point Class
上,結(jié)構(gòu)圖如下:
優(yōu)點:采用兩層索引機制,對object
變化提供比較好的彈性,在object
的nonstatic data member
有所改變時,而應(yīng)用程序代碼沒有改變,這時是不需要重新編譯的。
缺點:空間和時間上的效率降低,具體原因可以參考簡單對象模型的缺點分析。
3. C++ 對象模型
Stroustrup
早期設(shè)計的C++對象模型是從簡單對象模型改進而來的,并對內(nèi)存空間和存取時間進行了優(yōu)化。主要是將nonstatic data members
存儲在每一個object
中,而static data members
以及所有的function members
被獨立存儲在所有object
之外。
對虛函數(shù)的支持主要通過以下幾點完成的:
所有包含虛函數(shù)或者繼承自有虛函數(shù)基類的class
都會有一個virtual table
,該虛函數(shù)表存儲著一堆指向該類所包含的虛函數(shù)的指針。
每個class
所關(guān)聯(lián)的type_info object
也是由virtual table
存儲的,一般會存在該表格的首個slot
,type_info
用于支持runtime type identification
(RTTI)。
如果將C++對象模型應(yīng)用在Point Class上,結(jié)構(gòu)圖如下:
優(yōu)點:空間和存取效率高,所有static data members
以及所有的function members
被獨立存儲在所有object之外,可以減少每個object
的大小,而nonstatic data members
存儲在每一個object
中,又提升了存取效率。
缺點:如果應(yīng)用程序的代碼未曾更改,但所用到的class
的nonstatic data members
有所更改,那么那些代碼仍然需要全部重新編譯,而前面的表格驅(qū)動模型在這方面提供了較大的彈性,因為他多提供了一層間接性,當然是付出了時間和空間上的代價。
在加上繼承情況下的對象模型
C++支持單繼承、多繼承、虛繼承,下面來看下base class
實體在derived class
中是如何被構(gòu)建的。
簡單對象模型中可以通過derived class object
中的一個slot
來存儲base class subobject
的地址,這樣就可以通過該slot
來訪問base class
的成員。這種實現(xiàn)方式的主要缺點是:因為間接性的存儲而導(dǎo)致空間和存取時間上存在額外負擔;優(yōu)點是:derived class
的結(jié)構(gòu)不會因為base class
的改變而改變。
表格驅(qū)動對象模型中可以利用一個類似base class table
的表格來存儲所有基類的信息。該表格中存儲一系列slot
,每個slot
存儲一個base class
的地址。這種實現(xiàn)方式的缺點是:因為間接性的存儲而導(dǎo)致空間和存取時間上存在額外負擔;優(yōu)點是:一是所有繼承的class
都有一致的表現(xiàn)形式(包含一個base table
指針,指向基類表)與基類的大小和數(shù)目沒有關(guān)系,二是base class table
增加了子類的擴展性,當基類發(fā)生改變時,可以通過擴展、縮小或者更改base class table
來進行調(diào)整。
以上兩種實現(xiàn)方式都存在一個重要的問題,就是由于間接性而導(dǎo)致的空間和時間上的額外負擔,并且該間接性的級數(shù)會隨著繼承的深度而增加。
C++ 最初采用的繼承模型并不采用任何間接性,所有基類的數(shù)據(jù)直接存儲在子類當中,這樣在存儲結(jié)構(gòu)和訪問效率上是最高效的。當然也有缺點:當base class members
有任何改變,用到此base class
或者derived class
的對象必須重新編譯。在C++ 2.0引入了virtual base class
,需要一些間接性的方式來支持該特性,一般會導(dǎo)入一個virtual base class table
或者擴展已有的virtual table
。
總結(jié)
以上就是深入研究C++的對象模型的全部內(nèi)容,希望本文的內(nèi)容對大家有所幫助。
上一篇:VC++實現(xiàn)文件與應(yīng)用程序關(guān)聯(lián)的方法(注冊表修改)
欄 目:C語言
本文標題:深入理解C++的對象模型
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2120.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10深入理解約瑟夫環(huán)的數(shù)學(xué)優(yōu)化方法
- 01-10深入二叉樹兩個結(jié)點的最低共同父結(jié)點的詳解
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10深入第K大數(shù)問題以及算法概要的詳解
- 01-10深入解析最長公共子串
- 01-10c++中inline的用法分析
- 01-10深入理解鏈表的各類操作詳解


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 04-02jquery與jsp,用jquery
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10C#中split用法實例總結(jié)