C++物件模型 筆記1
阿新 • • 發佈:2018-11-19
C++類中的函式不會佔用類本身的記憶體,而是類的宣告的非行內函數只會誕生一個函式體。C++在佈局和存取時間上主要的額外負擔由virtual
引起:
- virtual function機制 執行期動態繫結
- virtual base class機制 多次繼承中,單一的基類被共享
C++的基本面向物件模型:
- 所有的非靜態資料成員存放到
class
內部 - 靜態成員和函式存放到
class
外部
虛擬函式的支援步驟:
- 每個
class
產生一些指向virtual function
的指標,存放在一個表格中,稱為虛表,virtual table
vtbl
) - 每個
class
新增一個指標,指向相關的vtbl
,稱為vptr
該方式的好處是空間和存取時間效率高,缺點在於如果程式程式碼沒變,但是class
的非靜態成員改變了,那麼程式碼就要重新編譯。
虛擬繼承情況下,不管發生多少次繼承,永遠只有一個基類。可以理解為一個bptr,有點在於減少二義性,缺點在於時空表現的效率低。
C++支援多型的方式,僅僅使用下列方法是安全的:
-
使用指標的操作,子類的指標可以指向基類:
shape *ps = new circle(); // circle是shape的子類
-
使用
virtual function
機制:ps->rotate(); // 呼叫實際的函式
-
使用
dynamic_cast
和typeid
運算子:if (circle *pc = dynamic_cast<circle*>(ps) ) ...
多型最主要的用法是使用共同的介面進行封裝,一般來說這個介面定義在一個抽象的基類中。這就像Java的interface
關鍵字,不過C++沒有介面的具體關鍵字,實際中可以使用多重繼承虛基類來完成,在執行期進行檢查到底是執行哪一個子類的函式。
動態繫結操作會在傳入引用和指標的時候發生。
一個class object
佔用記憶體的大小取決於下面三個:
- 非靜態成員總和的大小
- 需要
alignment
padding
的空間 - 為了支援
virtual
而產生的空間,主要是各種虛表。對於指標(不包含智慧指標)來說,它們佔用的記憶體大小是固定的。
如果把子類轉換成基類,那麼子類會被切割,只保留基類的部分。
只有下面4種情況下,才會有自動生成的預設建構函式:
- 如果一個
class
沒有建構函式,而它的成員含有預設建構函式,此時會產生一個建構函式,不過合成操作只有真正需要呼叫時才會發生。 - 基類由預設建構函式,派生類沒有定義建構函式,此時會合成一個預設建構函式,而且會呼叫基類的建構函式,根據宣告的次序執行
- 帶有
virtual function
的class
。 當一個class
宣告(或繼承)一個virtual function
;class
派生自一個繼承串鏈,其中有一個或者多個虛基類 - 帶有虛基類的類
必須使用引數初始化列表的情況:
- 初始化引用物件
- 初始化
const
物件 - 呼叫基類的建構函式,且建構函式擁有一組引數
- 呼叫類成員的建構函式,而且有引數
初始化列表的順序不一定按照宣告的順序執行,這點要格外注意!!!一般來說,很多時候初始化列表的效率更高,因此在意義明確的情況下,儘量使用初始化列表!!!