6

如果我在窗体上实现一个接口,例如TMyForm = class(TForm, IMyInterface),当没有更多的接口引用对象时,它会释放自己吗?似乎没有,尽管我无法弄清楚 TForm 是如何被引用计数的(如果有的话)。我担心当接口引用超出范围时表单会被释放,但这似乎没有发生。

我想这个问题有两个部分,首先是表单是否会被意外释放(真正的问题),其次是表单是如何被引用计数的。

4

2 回答 2

15

TForm派生自TComponent,它实现_AddRef()_Release()禁用自身的引用计数。因此,任何由任何TComponent后代类实现的接口,例如TForm,在释放接口时默认不会释放其实现TComponent对象。

但是,如果将IVCLComObject接口分配给TComponent.VCLCOMObject属性,TComponent则将引用计数委托给该对象,以便在其引用计数降至 0 时释放该对象(TComponent不会增加其引用的引用计数IVCLCOMObject)。

这对 的所有后代都有效,除非它们通过覆盖和手动TComponent实现自己的任何引用计数。_AddRef()_Release()

于 2013-12-04T22:09:22.860 回答
0

如果您在表单中实现接口,则值得添加自己的接口

_Release as follows:

    function _Release: Integer; stdcall;

function TMyInterfacedForm._Release: Integer;
begin
  result:=-1; 
end;

我发现可以释放带有接口的表单,然后在局部变量超出范围时调用 _Release。这可能会产生访问冲突,因为 Tcomponent 实现会检查是否设置了 FVCLComObject

  if FVCLComObject = nil then
    Result := -1   // -1 indicates no reference counting is taking place
  else
    Result := IVCLComObject(FVCLComObject)._Release;

由于在这个阶段,FVCLComobject 是未定义的,因此可能会出现烦人的 A/V 异常。通过硬连线 -1,可以安全地调用它而不会触发异常。

于 2015-11-25T06:08:33.750 回答