我是用下面的代码来模拟类的创建过程的: function InternalCreateInstance(classType: TClass; constructorMethod: TRttiMethod; const arguments: TArray<TValue>): TObject; // TEMP procedure DestroyInstance(instance: TObject); begin instance.Destroy; end; begin Result := classType.NewInstance; try constructorMethod.Invoke(Result, arguments); except on Exception do begin DestroyInstance(Result); raise; end; end; try Result.AfterConstruction; except on Exception do begin Result.BeforeDestruction; DestroyInstance(Result); raise; end; end; end; 我测试过,如果在构造函数里面抛出异常的话,BeforeDestruction并不会被执行,但Destroy方法本身会被执行。
已经告诉你了,destructor 有个1字节的隐含参数,不会自己试么?
哈哈,谢谢大侠的指点,确实如此。type TDestroyMethod = procedure(value: ShortInt) of object; var obj: TObject; method: TMethod; begin obj := TObject.Create; method.Code := @TObject.Destroy; method.Data := obj; TDestroyMethod(method)(1); // 大于0就不会调用BeforeDestruction end; 再请教一个相关的问题,如何调用对象实例相关的VMT中的Destroy方法?必须要用汇编吗?
function InternalCreateInstance(classType: TClass;
constructorMethod: TRttiMethod; const arguments: TArray<TValue>): TObject; // TEMP
procedure DestroyInstance(instance: TObject);
begin
instance.Destroy;
end;
begin
Result := classType.NewInstance;
try
constructorMethod.Invoke(Result, arguments);
except
on Exception do
begin
DestroyInstance(Result);
raise;
end;
end;
try
Result.AfterConstruction;
except
on Exception do
begin
Result.BeforeDestruction;
DestroyInstance(Result);
raise;
end;
end;
end;
我测试过,如果在构造函数里面抛出异常的话,BeforeDestruction并不会被执行,但Destroy方法本身会被执行。
TDestroyMethod = procedure(value: ShortInt) of object;
var
obj: TObject;
method: TMethod;
begin
obj := TObject.Create;
method.Code := @TObject.Destroy;
method.Data := obj;
TDestroyMethod(method)(1); // 大于0就不会调用BeforeDestruction
end;
再请教一个相关的问题,如何调用对象实例相关的VMT中的Destroy方法?必须要用汇编吗?
我调试过,如果直接在构造函数内抛出异常,那么AfterConstruction自然不会执行,而且编译器会自动执行子类的Destroy,此时并不会执行BeforeDestruction。
所以我才猜想在调用Create函数的异常处理代码中直接调用Destroy方法,并传入隐藏的参数。不知道Seamour大侠是怎么判断的?
不看反汇编也很不难猜处理过程,首先就是肯定是有通用性的,否则编译器也太累。然后就是要避免一些特殊情况引发的逻辑错误,最重要的是 inherited 会不会导致重复调用 BeforeDestruction 和 FreeInstance。如果让我来设计的话,我会采用怎样的流程,想明白这个别的也就都好办了