天天看點

Inside C++ object Model--對象模型概述

在c中, "資料"和"處理資料的操作"是分開聲明的, 語言本身并沒有支援"資料和函數"之間的關聯性. 這種稱為"procedural", 由一組算法函數所驅動, 他們處理的是共同的外部資料.

而c++, 則在程式風格, 更在程式的思考上有明顯的差異, 它以adt或class hierarchy的資料封裝建立資料和操作的關聯性. 在軟體工程的眼光來看更為合理.

但是程式員往往出于效率和簡易性考慮而選擇c.

那麼使用c++是否就一定意味着低效了...

其實c++在布局以及存儲時間上的額外負擔主要是由"virtual"引起的,

the virtual function mechanism in its support of an efficient run-time binding, and

a virtual base class in its support of a single, shared instance of a base class occurring multiple times within an inheritance hierarchy.

一般而言, 并沒有什麼天生的理由說c++一定比c龐大或遲緩.

對象模型

作為此書讨論的基礎, 首先要來分析一下c++的對象模型. 所謂對象模型, 就是在記憶體中怎麼樣來存儲一個對象.

對于對象的存儲, 下面有3種模型

簡單對象模型

這個模型, 顧名思義, 就是為了盡量減低c++編譯器的設計複雜度而開發的, 當然簡單帶來的是空間和執行期的低效.

這個模型中, 對象就是一系列slots, slot中存放了指向members的指針, members按程式中的聲明順序排列.

對象中并不實際存放members, 隻是存放member的指針, 這樣的好處是member的類型不會影響對象的存儲空間.

但是降低了通路效率,  和存儲效率, 由于需要通過指針間接通路, 并要額外存儲指針.

表格驅動對象模型

這個模型, 相對于簡單模型, 更加抽象, 它會把data member和function member分别放在兩個table中,

the member function table 和簡單模型一樣存放的是函數指針. the data member table 直接存放的是data本身.

而對象本身隻存放這兩個table的指針, 這樣最大的好處是, 對象大小是固定的, 無論members怎樣改變.

Inside C++ object Model--對象模型概述

c++對象模型

c++模型從簡單對象模型派生而來, 并對記憶體空間和存取時間做了優化. 各個member的存儲方法如下,

nonstatic data members are allocated directly within each class object.

static data members are stored outside the individual class object.

static and nonstatic function members are also hoisted outside the class object.

virtual functions are supported in two steps:

a table of pointers to virtual functions is generated for each class (this is called the virtual table ).

a single pointer to the associated virtual table is inserted within each class object (traditionally, this has been called the vptr ).the type_info object associated with each class in support of runtime type identification (rtti) is also addressed within the virtual table, usually within the table's first slot.

如下圖所示, 對于c++對象模型, 對象内隻會儲存nonstatic data members和vptr, 這個模型的優點是在于空間和存取時間的效率, 缺點是由于考慮存取效率把nonstatic data members直接存放在對象中, 導緻任何資料成員的改動都會影響類對象的大小. 此處表格驅動對象模型就提供了較大的彈性, 不過魚和熊掌不能兼得. 在設計時, 就需要根據實際需要進行取舍, c++更看重效率, 而corba這樣的元件平台, 就會選擇耦合度更低的表格驅動模型, 以利于當類成員改變後, 可以不需重新編譯客戶代碼(因為對于這種模型, 對象大小是不變的).

Inside C++ object Model--對象模型概述

繼承的對象模型

前面讨論了基本的c++對象模型, 如果加入了繼承語言特性, 對象模型又要做什麼樣的改動

這個問題就是怎樣在記憶體中存放父類, 派生類, 以及建立之間的關系.

簡單的想法就是, 在對象中增加一個slot去存放父類對象指針, 有幾個父類就增加幾個slots

更透明的方法是, 專門生成一個base class table來存放所有父類指針, 并在對象中增加一個bptr來指向這個table.

這個方法的問題就是由于間接性導緻的效率問題, 但優點就是對象對于繼承的一緻的表現方式, 可以任意修改父類, 而不會影響該類對象本身

前面說了c++更看重效率, 是以它沒有采用任何的間接方法,

the data members of the base class subobject are directly stored within the derived class object.

缺點很明顯,就是任意base class發生改變, 所有用到該類的派生類都需要重新編譯.

關于c++對于虛基類的處理會在後面章節讨論...

本文章摘自部落格園,原文釋出日期:2011-07-05

繼續閱讀