虛繼承
虛繼承用於解決多繼承條件下的菱形繼承問題(浪費存儲空間、存在二義性)。
底層實現原理與編譯器相關,一般通過虛基類指針和虛基類表實現,每個虛繼承的子類都有一個虛基類指針(占用一個指針的存儲空間,4字節)和虛基類表(不占用類對象的存儲空間)(需要強調的是,虛基類依舊會在子類里面存在拷貝,只是僅僅最多存在一份而已,並不是不在子類里面了);當虛繼承的子類被當做父類繼承時,虛基類指針也會被繼承。
實際上,vbptr 指的是虛基類表指針(virtual base table pointer),該指針指向了一個虛基類表(virtual table),虛表中記錄了虛基類與本類的偏移地址;通過偏移地址,這樣就找到了虛基類成員,而虛繼承也不用像普通多繼承那樣維持着公共基類(虛基類)的兩份同樣的拷貝,節省了存儲空間。
1 #include<iostream> 2 using namespace std; 3 4 class A //大小為4 5 { 6 public: 7 int a; 8 double b; 9 }; 10 //在32位環境下,大小為12,變量a,b共8字節,虛基類表指針4; 11 //在64位環境下,變量a 4個字節,b 4個字節,虛基類表指針8個字節,為了對齊,大小總共24 12 class B :virtual public A 13 { 14 public: 15 int b; 16 }; 17 18 //與B一樣 19 class C :virtual public A 20 { 21 public: 22 int c; 23 }; 24 25 //在32位環境下,大小為24,變量a,b,c,d共16,B的虛基類指針4,C的虛基類指針 26 class D :public B, public C 27 { 28 public: 29 int d; 30 }; 31 32 int main() 33 { 34 cout << sizeof(A) << endl; 35 cout << sizeof(B) << endl; 36 cout << sizeof(C) << endl; 37 cout << sizeof(D) << endl; 38 cout << sizeof(void *) << endl; 39 40 system("pause"); 41 return 0; 42 }
