非常有难度的代码(100分)

  • 主题发起人 主题发起人 38152977
  • 开始时间 开始时间
3

38152977

Unregistered / Unconfirmed
GUEST, unregistred user!
class function TObject.InitInstance(Instance: Pointer): TObject;
{$IFDEF PUREPASCAL}
var
IntfTable: PInterfaceTable;
ClassPtr: TClass;
I: Integer;
begin
FillChar(Instance^, InstanceSize, 0);
PInteger(Instance)^ := Integer(Self);
ClassPtr := Self;
while ClassPtr <> nil do
begin
IntfTable := ClassPtr.GetInterfaceTable;
if IntfTable <> nil then
for I := 0 to IntfTable.EntryCount-1 do
with IntfTable.Entries do
begin
if VTable <> nil then
PInteger(@PChar(Instance)[IOffset])^ := Integer(VTable);
end;
ClassPtr := ClassPtr.ClassParent;
end;
Result := Instance;
end;

谁能帮我详细解说每一行。特别是 PInteger(@PChar(Instance)[IOffset])^ := Integer(VTable); 100分
 
PInteger(@PChar(Instance)[IOffset])^ := Integer(VTable);

向Instance的第IOffset位置的指针地址写入Integer(VTable)这个数据

我想应该是这样的。嘿嘿。
 
这是初始化一个指针,该指针已经申请好内存,需要做的是对象的虚函数表写入到内存中。
 
class function TObject.InitInstance(Instance: Pointer): TObject;
{$IFDEF PUREPASCAL}
var
IntfTable: PInterfaceTable; //接口表
ClassPtr: TClass; //类指针
I: Integer;
begin //这个方法是类方法(对应C++中叫静态方法),其中Self不是实例,而是类本身.
FillChar(Instance^, InstanceSize, 0); //把实例全部初始化为0, InstanceSize是实例的大小
PInteger(Instance)^ := Integer(Self); //将类地址存放在开始的四个字节中
ClassPtr := Self; //给ClassPtr赋值当前类
while ClassPtr <> nil do //循环把自己从所有祖先类继承来的接口表每一项的虚方法表都初始化为和祖先类一样
begin
IntfTable := ClassPtr.GetInterfaceTable; //获取ClassPtr指向的类的接口表
if IntfTable <> nil then //如果接口表不为空,也就是存在接口表
for I := 0 to IntfTable.EntryCount-1 do //遍历整个接口表中的单元
with IntfTable.Entries do
begin
if VTable <> nil then //如果接口表中项IntfTable.Entries的虚方法表不为空
PInteger(@PChar(Instance)[IOffset])^ := Integer(VTable); //根据接口表中的项提供的偏移地址,把该对象的接口的虚方法表赋值为ClassPtr的接口表的第I项的虚方法表也就是ClassPtr.GetInterfaceTable.Entries.VTable
end;
ClassPtr := ClassPtr.ClassParent; //给ClassPtr赋值ClassPtr的父类
end;
Result := Instance; //返回实例
end;


Delphi的对象内存分布是:对象后面跟接口表,接口表每一项对应一个接口。接口方法都是虚方法,所以每一个接口都有一个虚方法表。当然接口如果诶有方法的话虚方法表就是空的。
 
接受答案了.
 
后退
顶部