首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在TObject中释放TInterfacedObject成员

如何在TObject中释放TInterfacedObject成员
EN

Stack Overflow用户
提问于 2018-02-26 07:03:47
回答 2查看 999关注 0票数 3

我知道一个接口对象是引用计数,所以不需要手动释放它。但是,如果它有一个TObject继承的成员,我是否应该在析构函数中手动释放这个成员?

考虑以下代码:

代码语言:javascript
复制
program Project2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes;

type
  ITestInterface = interface(IInvokable)
    ['{A7BDD122-7DC6-4F23-93A2-B686571AB2C8}']
    procedure TestMethod;
  end;

  TTestObj = class(TInterfacedObject, ITestInterface)
    constructor Create;
    destructor Destroy; override;
  private
    FData: TStrings;
  public
    procedure TestMethod;
  end;

{ TTestObj }

constructor TTestObj.Create;
begin
  FData := TStringList.Create;
end;

destructor TTestObj.Destroy;
begin
  Writeln('Destroy'); // This line won't apear in the console ouput as the destructor won't be called.
  FData.Free;         // Who guarantees this member will be freed ?

  inherited;
end;

procedure TTestObj.TestMethod;
begin
  Writeln('TestMethod');
end;

{ Main }

procedure Main;
var
  TestObj: TTestObj;
begin
  TestObj := TTestObj.Create;
  TestObj.TestMethod;
  TestObj := nil;     // TestObj should be freed at this moment ?
end;

begin
  Writeln('Program start!');
  Main;
  Writeln('Program end.');
  Readln;
end.

程序输出:

代码语言:javascript
复制
Program start!
TestMethod
Program end.

这意味着构造函数没有被调用,成员FData也没有被释放?

我该怎么办?提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-26 07:23:34

TTestObj中的代码很好。您必须实现一个破坏FData的析构函数,就像您所做的那样。

问题就在别处。接口对象不会被销毁,因为您从未触发任何引用计数。您需要通过接口变量引用接口对象。替换

代码语言:javascript
复制
TestObj: TTestObj

使用

代码语言:javascript
复制
TestObj: ITestInterface

完成此更改后,接口引用代码将在首次分配给TestObj变量时添加引用。

顺便说一句,你不需要这句话

代码语言:javascript
复制
TestObj := nil

TestObj变量超出作用域时,引用计数将降至零,实现对象将被销毁。

票数 7
EN

Stack Overflow用户

发布于 2018-02-26 07:20:52

您必须像往常一样释放析构函数中的TStrings (除非使用ARC编译器)。

父对象(TTestObject)被自动释放-- ,但只有当它被用作接口时--而不是它引用的对象,比如FData

您使用对象作为对象,但必须将其用作接口以获得自动引用计数:

代码语言:javascript
复制
var
  TestObj: ITestInterface;

但是,与TTestObject是否实现接口无关,您必须始终释放析构函数中的任何聚合对象,就像您所做的那样。

同样,只有在使用不为对象实现ARC的编译器(即,如果目标是Win32、Win64、macOS)时,上述情况才是正确的。

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

https://stackoverflow.com/questions/48983070

复制
相关文章

相似问题

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