将对象引用作为接口传递

Jus*_*tMe 2 delphi oop interface delphi-7

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

  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;
Run Code Online (Sandbox Code Playgroud)

关闭主窗体后,它给我一个AV和内存泄漏 - 整个主要形式泄露.如果我传递nilTSomeObject构造函数一切都很好.编译器是否FSomeInterface通过引用计数释放,我不应该尝试SomeObject在mainForm中释放destructor?我怎么能避免呢?

Uwe*_*abe 7

TSomeObject继承自TInterfacedObject,因此被引用计数.您的TSomeObject实例未被引用计数,应该被接口变量删除或替换.

如果需要在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;
Run Code Online (Sandbox Code Playgroud)