13.多重繼承(菱形繼承),虛繼承,虛基類
阿新 • • 發佈:2018-12-21
多重繼承:
就是一個派生類多個基類,幾乎與單繼承是一致的。
唯一考點: 菱形繼承結構(B類C類繼承A類,D類繼承A類。),產生問題,派生類有多份基類的資料。 解決辦法:B C都採用虛繼承,只有一個虛繼承也無法解決該問題。
虛繼承:
厲害了,virtual不僅可以宣告虛擬函式,還可以設定繼承方式:虛繼承
被採用虛繼承的基類 A,稱為虛基類
此時派生類的大小擴大:會有虛基類指標B,C都會產生一個虛基類指標 vbptr(virtual base ptr)。並且如果基類有虛擬函式,所以派生類還會有虛擬函式指標vfptr。
重點:
正常繼承,派生類物件的記憶體先放: 基類物件,再放自己的成員變數。 並且這個是派生類包含
將B,C相同繼承下來的A,放到最後面,在原來的地方會留下虛基類指標。b一個 c一個,還有個虛基類表(第一行 存放的是虛基類指標自己的偏移地址,一般是0. 第二行存放的是,虛基類指標到A成員變數的偏移地址),存放的是A成員變數的偏移量,用這個指標可以找到A的成員變數。
舉個栗子:
class A { public: A(int data) :ma(data){ cout << "A()" << endl; } ~A(){ cout << "~A()" << endl; } protected: int ma; }; //////////////////////////////////////////////////// class B : virtual public A 就在這!!!!!!!!!!! { public: B(int data) :A(data), mb(data){ cout << "B()" << endl; } ~B(){ cout << "~B()" << endl; } protected: int mb; }; class C : virtual public A 就在這!!!!!!!!!!! { public: C(int data) :A(data), mc(data){ cout << "C()" << endl; } ~C(){ cout << "~C()" << endl; } protected: int mc; }; //////////////////////////////////////////////////// class D : public B, public C { public: D(int data) :md(data),A(data), B(data), C(data) { cout << "D()" << endl; } ~D(){ cout << "~D()" << endl; } void show(){ cout << ma << endl; } protected: int md; }; int main() { cout << sizeof(D) << endl; D d(10); d.show(); int *p = (int*)&d; 將B的vbptr地址給了p int *q = (int*)*p; 將vbptr解引用也就是B的vbtable。 q += 1; +1後就指向了偏移量 int offset = *q; 記錄姐引用後的偏移量 char *p1 = (char*)&d;換成char才可以 p1 += offset; 加上偏移量,之後p1就指向ma *(int*)p1 = 30; 更改ma的值 d.show(); return 0; }