一、C++中的對象模型
1、 概念
語言中直接支持面向對象程序設計的部分;
對於各種支持的底層實現機制。(沒看懂……)
2、 類中的成員分類
a) 成員函數
i. static function
ii. non static function
iii. virtual function
b) 數據成員
i. static member data
ii. non static member data
3、 C++對象模型
a) 類對象內存布局中的包括
i. non static member data
ii. vptr(虛函數表指針)
iii. vbptr(虛基類表指針)
b) 不包括
i. static member data(存儲在靜態存儲區)
ii. 成員函數(存儲在代碼區)
c) virtual table
簡稱vtbl。存放着指針,這些指針指向該類每一個虛函數。虛表中的函數地址將按聲明時的順序排列。vtbl在類聲明后就形成了,vptr是編譯器生成的。
d) vptr的位置一般放在一個類對象的最前端。
e) 虛基類表
vbptr指向的表,用於存放虛繼承中,虛基類存儲相對於虛基類表指針的偏移量。
二、繼承類型
1、普通繼承(不包含虛函數)
a、單繼承
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Derive:public Base { public: Derive (int a = 2):derive(a){} void fun1(){cout << base1 << endl;} int derive; };
b、多繼承
class Base1 { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2 { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
c、菱形繼承
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Base1:public Base { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2:public Base { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
注:菱形繼承存在二義性問題,編譯都不通過,只能通過指定特定基類的方式進行訪問基類變量。
Derive d;
d.base =3; // 不正確
d.Base1::base = 3; // 正確
2、普通繼承(包含虛函數)
a、單繼承(包含虛函數)
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Derive:public Base { public: Derive (int a = 2):derive(a){} virtual void fun0(){}; virtual void fun1(){cout << derive << endl;} int derive; };
注:派生類中新增的虛函數追加到虛函數表后面。
b、多繼承(包含虛函數)
class Base1 { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2 { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
注:派生類中新增的虛函數,追加到第一個基類的虛函數表的后面。
c、菱形繼承(包含虛函數)
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Base1:public Base { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2:public Base { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
注:分析時,由上到下依次分析。存在二義性問題和內存冗余問題。
3、虛繼承(不包含虛函數)
新增虛基類指針,指向虛基類表,虛基類表中首項存儲虛基類指針的偏移量,接下來依次存儲虛基類的偏移量(偏移量是相對於虛基類表指針的存儲地址)。
a、單虛繼承(不包含虛函數)
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Base1:virtual public Base { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; };
b、多虛繼承(不包含虛函數)
class Base1 { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2 { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive:virtual public Base1, virtual public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
c、菱形虛繼承(不包含虛函數)
第一種形式:
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Base1:virtual Base { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2:virtual Base { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive:virtual public Base1, virtual public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
注:分析派生類的內存分布時,也是由上到下分析。虛繼承將基類置於內存末尾,但是置於末尾的順序也有一定的次序。首先Base先放到末尾,然后Base1放到末尾,最后Base2放到末尾。
第二種形式:
class Base { public: Base (int a = 1):base(a){} void fun0(){cout << base << endl;} int base; }; class Base1:virtual public Base { public: Base1 (int a = 2):base1(a){} void fun1(){cout << base1 << endl;} int base1; }; class Base2:virtual public Base { public: Base2 (int a = 3):base2(a){} void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} void fun3(){cout << derive << endl;} int derive; };
注:分析的原則,從上到下,依次分析。
4、 虛繼承(包含虛函數)
a、單虛繼承(包含虛函數)
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Base1:virtual Base { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; };
與普通的包含虛函數的單繼承相比,派生類擁有自己的虛函數表以及虛函數表指針,而不是與基類共用一個虛函數表。注意虛函數表指針和虛基類表指針的存儲順序。
b、多虛繼承(包含虛函數)
class Base1 { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2 { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive:virtual public Base1, virtual public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
c、菱形虛繼承(包含虛函數)
第一種形式:
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Base1:virtual public Base { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2:virtual public Base { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive: public Base1, public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
第二種形式:
class Base { public: Base (int a = 1):base(a){} virtual void fun0(){cout << base << endl;} int base; }; class Base1:virtual public Base { public: Base1 (int a = 2):base1(a){} virtual void fun1(){cout << base1 << endl;} int base1; }; class Base2:virtual public Base { public: Base2 (int a = 3):base2(a){} virtual void fun2(){cout << base2 << endl;} int base2; }; class Derive: virtual public Base1,virtual public Base2 { public: Derive (int value = 4):derive (value){} virtual void fun3(){cout << derive << endl;} int derive; };
自行腦補C++類對象的內存結構……