TGrandpaObject = class
public
procedure AVirtualMethod; virtual;
end;
TParentObject = class(TGrandpaObject)
public
procedure AVirtualMethod; override;
end;
TCurrentObject = class(TParentObject)
public
procedure AVirtualMethod; override;
end;
TCurrentObject的AVirtualMethod虚拟方法不希望调用父类TParentObject的AVirtualMethod方法的实现代码,而要直接继承调用祖父类TGrandpaObject的AVirtualMethod方法代码。
类的继承体系中,在VMT中,子类的VMT完全包含父类的VMT,而自身的虚拟方法则是附着在VMT父类虚拟方法表的后面,也就是说子类虚拟方法和父类虚拟方法的相对偏移量是相同的,只是子类的虚拟方法有覆盖时,子类VMT中该虚拟方法的地址被覆盖啦。因此,要跳过父类的虚拟方法而直接调用祖父类的虚拟方法代码,那么只要通过VMT的虚拟方法的相对偏移量找到祖父类的虚拟方法地址,然后调用即可。
procedure TCurrentObject.AVirtualMethod;
begin
asm
MOV EDX,VMTOFFSET AVirtualMethod // 虚拟方法VMT偏移量
MOV EAX,Self // 对象实例 => EAX
MOV ECX,[EAX] // 类VMT => ECX
MOV ECX,[ECX].vmtParent
MOV ECX,[ECX] // 父类VMT => ECX
MOV ECX,[ECX].vmtParent
MOV ECX,[ECX] // 祖父类VMT => ECX
MOV ECX,[ECX+EDX] // 祖父类虚拟方法地址 => ECX
CALL ECX // 方法调用
end;
end;
虚拟方法跳过父类继承调用祖父类的代码
最新推荐文章于 2024-01-29 11:49:29 发布