Delphi中的接口引用计数支持函数

我有THuman实现 interface 的类ICanTalk

但是每当我尝试检查人类是否可以说话时,Supports函数都会破坏对象实例,尽管代码中有引用。

我误解了什么?

procedure TForm1.Button1Click(Sender: TObject);
var
 Obj:TInterfacedObject;
begin
 Obj:=THuman.Create('Great guy');
 // if Supports(Obj, ICanTalk) then //Object destroyed here if uncommented
   (Obj as  ICanTalk).TalkTo(Memo1.Lines);
end;

执行

ICanTalk = interface
  ['{57E5EF90-EB11-421C-AAFB-18CD789C0956}']
    procedure TalkTo(List:TStrings);
  end;

THuman = class(TInterfacedObject, ICanTalk)
  private
    FName: string;
  public
    procedure TalkTo(List:TStrings);
    property Name:string read FName;
    constructor Create(const AName:string);
end;

constructor THuman.Create(const AName: string);
begin
 FName:=AName;
end;

procedure THuman.TalkTo(List: TStrings);
begin
 List.Add(Name+' says Hello World!');
end;

回答

这是预期的。当您阅读有关该Supports功能的文档时,您会发现:

警告

除了检查 TClass 是否实现接口的重载之外,所有其他版本的 Supports 都会从一个对象或另一个接口引用中提取一个接口引用,导致底层对象的引用计数增加,然后将在退出时释放接口(减少引用计数)。对于引用计数为零的对象,这将导致对象销毁。

var 
  Obj: TInterfacedObject;
begin
  Obj := TInterfacedObject.Create;
  if Supports(Obj, IInterface) then { ... at this point Obj will be freed }
end;

你写了,

尽管在代码中引用(在可见区域)

不,没有参考。您声明ObjTInterfacedObject(类实例变量——不是接口变量),因此没有引用计数。

如果您改为使用接口类型变量,它将使用引用计数:

var
  Obj: IInterface;


以上是Delphi中的接口引用计数支持函数的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>