C++虚继承

虚继承

虚继承用于解决多继承条件下的菱形继承问题(浪费存储空间、存在二义性)。

底层实现原理与编译器相关,一般通过虚基类指针虚基类表实现,每个虚继承的子类都有一个虚基类指针(占用一个指针的存储空间,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 }