64,649
社区成员
发帖
与我相关
我的任务
分享
class CommonBase
{
public:
int co;
static int sco;
void selfprint(){};
virtual void basevirtualprint(){};
};
class anotherbase:virtual public CommonBase
{
public:
int anco;
static int sanco;
void selfprint(){};
virtual void anothervirtualprint(){};
};
class thirdbase:virtual public CommonBase
{
public:
int thirdco;
void selfprint(){};
static int sthirdco;
virtual void basevirtualprint(){};
};
class fourthbase
{
public:
int fa;
static int sfa;
virtual void fourthvirtualprint(){};
};
class target :public anotherbase,public thirdbase,public fourthbase
{
public:
void selfprint(){};
int ta;
static int sta;
virtual void basevirtualprint(){};
};
int main()
{
target t;
anotherbase* pt = &t;
pt->co = 10;
return 0;
}
其中target对象内存结构为:
class target size(40):
+---
| +--- (base class anotherbase)
0 | | {vfptr}
4 | | {vbptr}
8 | | anco
| +---
| +--- (base class fourthbase)
12 | | {vfptr}
16 | | fa
| +---
| +--- (base class thirdbase)
20 | | {vbptr}
24 | | thirdco
| +---
28 | ta
+---
+--- (virtual base CommonBase)
32 | {vfptr}
36 | co
+---
target::$vftable@anotherbase@:
| &target_meta
| 0
0 | &anotherbase::anothervirtualprint
target::$vftable@:
| -12
0 | &fourthbase::fourthvirtualprint
target::$vbtable@anotherbase@:
0 | -4
1 | 28 (targetd(anotherbase+4)CommonBase)
target::$vbtable@thirdbase@:
0 | 0
1 | 12 (targetd(thirdbase+0)CommonBase)
target::$vftable@CommonBase@:
| -32
0 | &target::basevirtualprint
vs2005下汇编,一下是45 46行的汇编代码:
; Line 45
lea eax, DWORD PTR _t$[ebp] ;将t对象的地址传给eax
mov DWORD PTR _pt$[ebp], eax ;将eax值传给pt
; Line 46
mov ecx, DWORD PTR _pt$[ebp] ; ecx = pt
mov edx, DWORD PTR [ecx+4] ; edx = pt->vbptr
mov eax, DWORD PTR [edx+4] ; eax = pt->vbptr[1] (如对象结构图,vbtr[1]=28)
mov ecx, DWORD PTR _pt$[ebp] ; ecx = pt
mov DWORD PTR [ecx+eax+8], 10 ; *(pt+pt->vbptr[1]+8) = 10(其中8为co到CommonBase的offset)
class CommonBase
{
public:
int co;
static int sco;
void selfprint(){};
virtual void basevirtualprint(){};
};
class anotherbase:virtual CommonBase
{
public:
int anco;
static int sanco;
void selfprint(){};
virtual void anothervirtualprint(){};
};
class thirdbase:virtual CommonBase
{
public:
int thirdco;
void selfprint(){};
static int sthirdco;
virtual void basevirtualprint(){};
};
class fourthbase
{
public:
int fa;
static int sfa;
virtual void fourthvirtualprint(){};
};
class target :anotherbase,thirdbase,fourthbase
{
void selfprint(){};
int ta;
static int sta;
virtual void basevirtualprint(){};
};
这种继承情况下,anotherbase中成员co离anotherbase的开始地址与target中co离anotherbase的开始距离是不同的,所以这个偏移是没法锁死的。在编译期我们唯一可以确定的就是co与commonbase的偏移,这个是不管怎么继承都是固定的。所以在传入一个指针的情况下,我们并无法确定偏移。必须得借助虚基类表,来实现间接的跳转。