如何释放TInterfacedObject中的TObject成员

时间:2018-02-26 07:03:47

标签: delphi

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

请考虑以下代码:

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.

节目输出:

Program start!
TestMethod
Program end.

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

我该怎么办?提前谢谢。

1 个答案:

答案 0 :(得分:4)

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

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

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

var
  TestObj: ITestInterface;

但是TTestObject是否实现了接口是无关紧要的,你必须总是释放析构函数中的任何聚合对象。

同样,只有当您使用的编译器没有为对象实现ARC时(例如,如果您的目标是Win32,Win64,macOS),上述情况才会成立。