接口“递归”和引用计数

时间:2008-10-05 09:04:20

标签: delphi oop interface

接口有一个小问题。这是伪代码:

type
  Interface1 = interface
  end;

  Interface2 = interface
  end;

  TParentClass = class(TInterfacedObject, Interface1)
  private
    fChild : Interface2;
  public
    procedure AddChild(aChild : Interface2);
  end;

  TChildClass = class(TInterfacedObject, Interface2)
  private
    fParent : Interface2;
  public
    constructor Create(aPArent : Interface1);
  end;

任何人都能看到这个漏洞吗?我需要孩子引用它的父级,但引用计数在这种情况下不起作用。如果我创建一个ParentClass实例,并添加一个子类,那么父类永远不会被释放。我明白为什么。我如何绕过它?

4 个答案:

答案 0 :(得分:10)

引用计数引用有两个语义:它作为所有权的共享以及导航对象图的方式。

通常,在引用图的循环中的所有链接上都不需要这两种语义。也许只有父母自己的孩子,而不是相反?如果是这种情况,您可以通过将它们存储为指针来使子引用父弱链接,如下所示:

TChildClass = class(TInterfacedObject, Interface2)
private
  fParent : Pointer;
  function GetParent: Interface1;
public
  constructor Create(aPArent : Interface1);
  property Parent: Interface1 read GetParent;
end;

function TChildClass.GetParent: Interface1;
begin
  Result := Interface1(fParent);
end;

constructor TChildClass.Create(AParent: Interface1);
begin
  fParent := Pointer(AParent);
end;

如果实例树的根保证在某处保持活动,这是安全的,即你不依赖于只保留对树的一个分支的引用,并且仍然能够导航整个树的分支。 / p>

答案 1 :(得分:3)

嗯,当然的引用计数在这种情况下工作 - 它只是没有解决问题。

这是引用计数的最大问题 - 当你有一个循环引用时,你必须明确地'打破'它(例如,将一个接口引用设置为'nil')。这也是为什么引用计数实际上不是垃圾收集的替代品 - 垃圾收集器意识到循环可能存在并且当它们没有从“外部”引用时可以释放这种循环结构。

答案 2 :(得分:1)

您必须创建一个明确取消链接正确引用的方法。在这种情况下,无法使自动引用计数正常工作。

答案 3 :(得分:0)

在第一个示例中使用了函数指针,则循环引用问题不存在。 .NET使用委托,VB6使用事件。所有这些都具有不增加被指向对象的引用计数的好处。