delphi - 将对象引用作为接口(interface)传递

标签 delphi oop interface delphi-7

我将创建的对象传递给另一个对象的构造函数,该对象需要一个该对象实现的接口(interface)。

  ISomeInterface = interface
  ['{840D46BA-B9FB-4273-BF56-AD0BE40AA3F9}']
  end;

  TSomeObject = class(TInterfacedObject, ISomeinterface)
  end;

  TSomeObject2 = class
  private
    FSomeInterface: ISomeinterface;
  public
    constructor Create(SomeObject: ISomeInterface);
  end;

var
Form1: TForm1; // main form
SomeObject: TSomeObject;

constructor TSomeObject2.Create(SomeObject: ISomeInterface);
begin
  FSomeInterface := SomeObject;
end;

// main form creating
procedure TForm1.FormCreate(Sender: TObject);
var SomeObject2: TSomeObject2;
begin
  SomeObject := TSomeObject.Create;
  //  SomeObject2 := TSomeObject2.Create(nil);        // ok
  SomeObject2 := TSomeObject2.Create(SomeObject);     // not ok
  try
  // do some things
  finally
    SomeObject2.Free;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  SomeObject.Free; // if passed to a SomeObject2 Constructor - freeing it causing av
end;

在我关闭主窗体后,它给了我一个 AV 和内存泄漏——整个主窗体都泄漏了。 如果我将 nil 传递给 TSomeObject 构造函数,一切都很好。编译器是否通过引用计数释放 FSomeInterface 而我不应该尝试释放 mainForm destructor 中的 SomeObject?我该如何避免?

最佳答案

TSomeObject 继承自 TInterfacedObject,因此被引用计数。您的 TSomeObject 实例未进行引用计数,应将其删除或替换为接口(interface)变量。

如果您需要在 FormCreate 中创建的 TSomeObject 的实例,您应该将它分配给一个 ISomeInterface 类型的变量,这样引用计数也将为此工作。

另一种方法是继承自 TInterfacedPersistant 而不是 TInterfacedObject 以避免引用计数。

解释代码中发生的事情:

procedure TForm1.FormCreate(Sender: TObject);
var SomeObject2: TSomeObject2;
begin
  { Here you create the instance and assign it to a variable holding the instance.
    After this line the reference count of the instance is 0 }
  SomeObject := TSomeObject.Create;
  //  SomeObject2 := TSomeObject2.Create(nil);        // ok
  { Using the instance as a parameter will increase the reference count to 1 }
  SomeObject2 := TSomeObject2.Create(SomeObject);     // not ok
  try
  // do some things
  finally
    { Freeing SomeObject2 also destroys the interface reference FSomeInterface is
      pointing to (which is SomeObject), decreasing the reference count to 0, which
      in turn frees the instance of TSomeObject. }
    SomeObject2.Free;
  end;
  { Now, after SomeObject is freed, the variable points to invalid memory causing the
    AV in FormDestroy. }
end;

关于delphi - 将对象引用作为接口(interface)传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16273137/

相关文章:

delphi - 从转到调用Delphi dll

delphi - 在 Delphi 中调试 OutputDebugString 调用

delphi - Delphi中同一个程序拥有多个NT服务

java - 一个集合中不同类型对象的其他选项

c# - 如何覆盖自定义库类中的方法

c# - 如何在 3rd 方对象后面的 'sneak' 接口(interface)

oop - 接口(interface)的功能主要是为了使用函数而不知道类是如何构建的吗?

delphi - TIdThreadComponent OnTerminate 和 OnStopped 在哪个线程中执行?

python - 如何在python中使用对象名称作为变量

.net - 如何以编程方式(在运行时)向类添加接口(interface)