为什么TForm的_release不会调用析构函数?

时间:2014-12-09 09:15:48

标签: delphi interface vcl delphi-2006

为什么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的发布是什么?对我来说似乎很奇怪......

1 个答案:

答案 0 :(得分:3)

原因是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采用其他政策。