关于Delphi的VMT问题的深入讨论 (10分)

  • 主题发起人 主题发起人 cqxiangyi
  • 开始时间 开始时间
C

cqxiangyi

Unregistered / Unconfirmed
GUEST, unregistred user!
procedure TForm1.Button1Click(Sender: TObject);
var
varVMT1:TClass;
varVMT2:TClass;
begin
varVMT1 := form1.ClassParent;
varVMT2 := TClass(pointer(integer(form1.ClassType)+vmtParent)^);
//根据delphi的对象模型varVMT1和varVMT2值相等。但.....
if integer(varVMT1)=integer(varVMT2) then
ShowMessage('ok')
else
ShowMessage('noequal');
end;
难到其对象模型我搞错了?如何写varVMT1和varVMT2才相等??
 
vmtParent是指的是VMT表中-36偏移处的常量,在此位置中是存储的是指向父类VMT指针的指针,一些书说这个位置是存储的是父类VMT的指针是不正确的.搞清楚了这一点,以上代码可以改为:

procedure TForm1.Button1Click(Sender: TObject);
var
varVMT1:TClass;
varVMT2:TClass;
begin
varVMT1 := form1.ClassParent;
varVMT2 := TClass(pointer(ppointer(integer(form1.ClassType)+vmtParent)^)^);
if integer(varVMT1)=integer(varVMT2) then
ShowMessage('ok')
else
ShowMessage('noequal');
end;
这样varVMT1和varVMT2才都是得到的父类的元数据即VMT的指针,
其实
varVMT2 := TClass(pointer(ppointer(integer(form1.ClassType)+vmtParent)^)^);
上面这句还可改为:
varVMT2 := TClass(pointer(ppointer(pinteger(self)^+vmtParent)^)^);
这里的 (pinteger(self)^中的self是指向类实例的指针,(pinteger(self)^便得到self所指向的四个字节(类实例的头四个字节),这里面便是存放的是VMT的地址.(ppointer(pinteger(self)^+vmtParent)^便得VMT表偏移vmtParent即-36处的值,这里面便存储的是父类的VMT的地址,故(pointer(ppointer(pinteger(self)^+vmtParent)^)^)便是得其中的VMT的地址,TClass便是类型转换了.
一切就是如此, 只是大多数书中没有把VMT中的-36处的内容讲正确,或者说是错误的.特此向同行们提醒.







 
有道理,但是我还是搞不太明白。
 
学习!!。知道VMT是一个对象开始的四个字节,有什么方法可以知道每个VMT表的大小吗!!
 
to wind28
学习!!。知道VMT是一个对象开始的四个字节
-------------------------------------------------
你的说法应该是错误的。应该是一个对象开始的四个字节存储的是VMT的地址。
 
vxcvzxcvcxvcx
 
后退
顶部