虚函数在继承中的对象内存布局偏移

  • 2021 年 7 月 26 日
  • 筆記

A: int a1; int a2; virtual void fun1(){} virtual void fun2(){} 

B继承A,int b1; int b2;
 
A:
vptr指向数组首元素,数组元素是A::fun1 A::fun2函数地址
a1;
a2;
B:
A(vptr指向数组首元素,数组元素是A::fun1 A::fun2函数地址/a1/a2)
b1;
b2;
 
继承类覆盖基类虚函数,类B的虚函数表不同于类A的虚函数表,字面上的覆盖
A: int a1; int a2; virtual void fun1(){} virtual void fun2(){} 

B继承A,int b1; int b2; virtual void fun1(){}
A:
vptr指向数组首元素,数组元素是A::fun1 A::fun2函数地址
a1;
a2;
B:
A(vptr指向数组首元素,数组元素是B::fun1 A::fun2函数地址/a1/a2)
b1;
b2;
 
派生类新增虚函数,类B的虚函数表不同于类A的虚函数表,字面上的新增
A: int a1; int a2; virtual void fun1(){} virtual void fun2(){} 

B继承A,int b1; int b2; virtual void fun3(){}
A:
vptr指向数组首元素,数组元素是A::fun1 A::fun2函数地址
a1;
a2;
B:
A(vptr指向数组首元素,数组元素是A::fun1 A::fun2 C::fun3函数地址/a1/a2)
b1;
b2;
 
多继承,既覆盖又新增,类ABC的虚函数表不同
A:int a1;int a2;virtual void fun1(){}virtual void fun2(){}
B:int b1;int b2;virtual void fun3(){}virtual void fun4(){}
C继承AB:int c1;int c2;virtual void fun1(){}virtual void fun4(){}virtual void fun5(){}virtual void fun6(){}
A:
vptr指向数组首元素,数组元素是A::fun1 A::fun2 函数地址
a1;
a2;
B:
vptr指向数组首元素,数组元素是B::fun3 B::fun4 函数地址
b1;
b2;
C:
A(vptr指向数组首元素,数组元素是C::fun1 A::fun2 C::fun5 C::fun6函数地址/a1/a2)
B(vptr指向数组首元素,数组元素是B::fun3 C::fun4函数地址/b1/b2)
c1;
c2;
 
如果类A没有虚函数,自然类C新增的虚函数放在类B的虚函数表后面[image:1627285376079.png]
 
如果AB都没有虚函数表,类C新建一个vptr还是要放在最前面
[image:1627285417393.png]
 
如果基类有虚函数,派生类只需要利用基类的vptr,把新增的虚函数接在基类vptr指向的虚函数表后面
如果基类没有虚函数,派生类需要自己的vptr,把新增的虚函数接在派生类vptr虚函数表