虛函數在繼承中的對象記憶體布局偏移

  • 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虛函數表
 
Tags: