Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 为什么要使用TForm';s_释放不调用析构函数?_Delphi_Interface_Vcl_Delphi 2006 - Fatal编程技术网

Delphi 为什么要使用TForm';s_释放不调用析构函数?

Delphi 为什么要使用TForm';s_释放不调用析构函数?,delphi,interface,vcl,delphi-2006,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 TFor

为什么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类的发布方法:

function TInterfacedObject._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    Destroy;
end;


TInterfacedObject的_发布看起来很容易理解,但是TComponent的_发布做什么呢?对我来说似乎很奇怪…

原因是
t组件
采用了一种策略,即生命周期管理是类用户的责任,并且不会通过任何接口引用自动进行管理。该策略在
t组件中有明确的表述

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

你不能把这两种模式混在一起。所做的设计选择是,
t组件
将遵循第一种模式。因此,必须禁用接口引用计数。相比之下,
TInterfacedObject
采用了另一种策略。

我认为除了两种常用的模式之外,您还应该提到所有者模式,特别是因为它在TComponent中使用的是OP所指的模式。重读您的答案后,我会说TComponent没有遵循您第一个示例中的模式(在其中使用TMyObject),虽然可以这样做,但t组件子体的固有模式是所有权模型。@iamjoosy取决于作为
所有者传递的内容。传递
nil
,调用方仍然是所有者。传递
nil
以外的内容,另一个内容就成为所有者。基本上,这是同一件事。所有这些都是吗这些设计选择表明,将接口与表单(以及任何其他TComponent的后代)一起使用是一种不好的做法?嗯,您只需要小心。它可能会变得混乱。您需要将由
t组件支持的接口引用与其他接口引用区别对待。您不能在实现组件的生命周期结束后保留该接口引用。这可能很难安排。
var
  intf: IMyInterface;
....
intf := TMyObject.Create;
DoSomething(intf);
// the implementing object behind intf is destroyed when the last 
// interface reference leaves scope