語言中直接支持面向對象程序設計的部分;html
對於各類支持的底層實現機制。(沒看懂……)前端
i. static function函數
ii. non static function佈局
iii. virtual functionspa
i. static member data設計
ii. non static member data3d
i. non static member data指針
ii. vptr(虛函數表指針)code
iii. vbptr(虛基類表指針)htm
i. static member data(存儲在靜態存儲區)
ii. 成員函數(存儲在代碼區)
簡稱vtbl。存放着指針,這些指針指向該類每個虛函數。虛表中的函數地址將按聲明時的順序排列。vtbl在類聲明後就造成了,vptr是編譯器生成的。
vbptr指向的表,用於存放虛繼承中,虛基類存儲相對於虛基類表指針的偏移量。
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; };
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; };
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; // 正確
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; };
注:派生類中新增的虛函數追加到虛函數表後面。
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; };
注:派生類中新增的虛函數,追加到第一個基類的虛函數表的後面。
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; };
注:分析時,由上到下依次分析。存在二義性問題和內存冗餘問題。
新增虛基類指針,指向虛基類表,虛基類表中首項存儲虛基類指針的偏移量,接下來依次存儲虛基類的偏移量(偏移量是相對於虛基類表指針的存儲地址)。
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 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; };
第一種形式:
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; };
注:分析的原則,從上到下,依次分析。
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; };
與普通的包含虛函數的單繼承相比,派生類擁有本身的虛函數表以及虛函數表指針,而不是與基類共用一個虛函數表。注意虛函數表指針和虛基類表指針的存儲順序。
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; };
第一種形式:
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++類對象的內存結構……
注:上述虛函數中,若是派生類重寫了基類的虛函數,則對應虛函數表中的虛函數應該修改爲從新後的虛函數,即Base::fun()->Derive::fun()。