为什么TForm的_release方法不调用析构函数?
var
F, U : IUnknown;
procedure TForm1.btn1Click(Sender: TObject);
begin
U := IUnknown(TMyObject.Create); // MyIterfacedObject (inherits TInterfacedObject)
F := IUnknown(TMyForm.Create(nil));
end;
procedure TForm1.btn2Click(Sender: TObject);
begin
U := nil; // Calls destructor
F._Release; // Does not call destructor
F := nil; // Does not call destructor
end;
我看了一下TInterfaceObject和TComponent类的_release方法:
function TInterfacedObject._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
function TComponent._Release: Integer;
begin
if FVCLComObject = nil then
Result := -1 // -1 indicates no reference counting is taking place
else
Result := IVCLComObject(FVCLComObject)._Release;
end;
TInterfacedObject的_release似乎很容易理解,但是TComponent的_release做什么?对我来说似乎很奇怪
最佳答案
原因是TComponent
采用这样的策略:生存期管理是该类用户的责任,并且不由任何采用的接口引用自动管理。该政策在TComponent._Release
中明确表示。
function TComponent._Release: Integer;
begin
if FVCLComObject = nil then
Result := -1 // -1 indicates no reference counting is taking place
else
Result := IVCLComObject(FVCLComObject)._Release;
end;
您描述的一种常见方案的
FVCLComObject
等于nil
。因此,代码明确指出通过返回-1
不会进行引用计数。甚至有这样的评论。生命周期管理需要以一种或另一种方式完成。 Delphi代码的两种常用模式是:
呼叫者管理的生命周期
var
obj: TMyObject;
....
obj := TMyObject.Create;
try
DoSomething(obj);
finally
obj.Free; // the object is explicitly destroyed here
end;
尽管
TComponent
的用法通常与此有所不同,因为它的构造函数被传递给所有者组件。然后,此所有者负责销毁拥有的组件的责任。这样的模式如下所示:component := TMyComponent.Create(OwnerComponent);
... // now component will be destroyed when OwnerComponent is destroyed
生命周期由接口引用管理
var
intf: IMyInterface;
....
intf := TMyObject.Create;
DoSomething(intf);
// the implementing object behind intf is destroyed when the last
// interface reference leaves scope
您不能混合使用两种模式。进行了设计选择,使
TComponent
将遵循第一种模式。因此,必须禁用接口引用计数。相比之下,TInterfacedObject
采用其他策略。