如果我在窗体上实现一个接口,例如TMyForm = class(TForm, IMyInterface)
,当没有更多的接口引用对象时,它会释放自己吗?似乎没有,尽管我无法弄清楚 TForm 是如何被引用计数的(如果有的话)。我担心当接口引用超出范围时表单会被释放,但这似乎没有发生。
我想这个问题有两个部分,首先是表单是否会被意外释放(真正的问题),其次是表单是如何被引用计数的。
TForm
派生自TComponent
,它实现_AddRef()
并_Release()
禁用自身的引用计数。因此,任何由任何TComponent
后代类实现的接口,例如TForm
,在释放接口时默认不会释放其实现TComponent
对象。
但是,如果将IVCLComObject
接口分配给TComponent.VCLCOMObject
属性,TComponent
则将引用计数委托给该对象,以便在其引用计数降至 0 时释放该对象(TComponent
不会增加其引用的引用计数IVCLCOMObject
)。
这对 的所有后代都有效,除非它们通过覆盖和手动TComponent
实现自己的任何引用计数。_AddRef()
_Release()
如果您在表单中实现接口,则值得添加自己的接口
_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,可以安全地调用它而不会触发异常。