首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么TForm的_release不调用析构函数?

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

Stack Overflow用户
提问于 2014-12-09 09:15:48
回答 1查看 211关注 0票数 1

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

代码语言:javascript
复制
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;

我看了一下_release方法的TInterfaceObject和TComponent类:

代码语言:javascript
复制
function TInterfacedObject._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    Destroy;
end;

代码语言:javascript
复制
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做了什么呢?我觉得很奇怪..。

EN

回答 1

Stack Overflow用户

发布于 2014-12-09 09:23:19

原因是TComponent采用了这样一种策略,即生命周期管理是类的用户的责任,而不是由任何接口引用自动管理。这一政策在TComponent._Release中得到了明确的表达。

代码语言:javascript
复制
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代码中常用的两种模式是:

生命周期由调用方管理

代码语言:javascript
复制
var
  obj: TMyObject;
....
obj := TMyObject.Create;
try
  DoSomething(obj);
finally
  obj.Free; // the object is explicitly destroyed here
end;

不过,TComponent的使用通常与此略有不同,因为它的构造函数是传递给所有者组件的。然后,这个所有者负责销毁所拥有的部件。所以这个模式是这样的:

代码语言:javascript
复制
component := TMyComponent.Create(OwnerComponent);
... // now component will be destroyed when OwnerComponent is destroyed

由接口引用管理的生命周期

代码语言:javascript
复制
var
  intf: IMyInterface;
....
intf := TMyObject.Create;
DoSomething(intf);
// the implementing object behind intf is destroyed when the last 
// interface reference leaves scope

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27375170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档