【问题标题】:generic tree node structure: problem freeing the child nodes通用树节点结构:释放子节点的问题
【发布时间】:2020-05-15 10:27:08
【问题描述】:

基于这个GenericTree我实现了以下通用树节点结构:

type
  TTreeNode<T>=class
  private
    procedure FreeChildNodes; 
    procedure RemoveMyselfFromParentChildNodesList;
    function GetIndexInParentChildNodesList: Integer;
  public
    NodeData: T;
    ChildNodes: TList<TTreeNode<T>>;
    ParentNode: TTreeNode<T>;
    constructor Create(const AParentNode: TTreeNode<T>); overload;
    destructor Destroy; override;
  end;

implementation

constructor TTreeNode<T>.Create(const AParentNode: TTreeNode<T>);
begin
  inherited Create;
  ParentNode:=AParentNode;
  ChildNodes:=TList<TTreeNode<T>>.Create;
end;

destructor TTreeNode<T>.Destroy;
begin
  FreeChildNodes;
  RemoveMyselfFromParentChildNodesList;
  ChildNodes.Free;
  inherited;
end;

procedure TTreeNode<T>.FreeChildNodes;
var
  i: Integer;
begin
  for i := ChildNodes.Count-1 downto 0 do
  begin
    ChildNodes[i].Free;
  end;
  ChildNodes.Clear;
end;

function TTreeNode<T>.GetIndexInParentChildNodesList: Integer;
var
  i: Integer;
begin
  Result:=-1;
  if ParentNode<>nil then
  begin
    Result:=ParentNode.ChildNodes.IndexOf(Self);
  end;
end;

procedure TTreeNode<T>.RemoveMyselfFromParentChildNodesList;
begin
  if ParentNode<>nil then
  begin
    ParentNode.ChildNodes.Delete(GetIndexInParentChildNodesList);
  end;
end;

这工作正常。

现在我想创建一个具有特定对象类型的后代类。

对象类型是:

type
  TMyObject=class
  public
    Value: string;
    constructor Create; override;
    destructor Destroy; override;
  end;

还有新的后代类:

type
  TMyTreeNode=class(TTreeNode<TMyObject>)
  private
  public
    constructor Create(const AParentNode: TMyTreeNode); overload;
    destructor Destroy; override;
  end;

implementation

constructor TMyTreeNode.Create(const AParentNode: TMyTreeNode);
begin
  inherited Create(AParentNode);
  NodeData:=TMyObject.Create;
end;

destructor TMyTreeNode.Destroy;
begin
  NodeData.Free;
  inherited;
end;

当我用TMyTreeNode.Destroy 释放TMyTreeNode 时,继承的TTreeNode&lt;T&gt;.Destroy 被调用以递归地释放ChildNodes。问题是所有的 ChildNodes 都被TTreeNode&lt;T&gt;.Destroy 释放,因此TMyObjects 没有被释放,导致内存泄漏。

我还尝试使用TObjectList 而不是TList 来代替ChildNodes。但是,TObjectList 似乎在我释放子节点之前会自行销毁。

如何解决这个问题?

【问题讨论】:

    标签: delphi generics tree


    【解决方案1】:

    你可以使用:

    procedure TTreeNode<T>.FreeChildNodes;
    var
      i: Integer;
    begin
      for i := ChildNodes.Count-1 downto 0 do
      begin
        ChildNodes[i].NodeData.free;
        ChildNodes[i].Free;
      end;
      ChildNodes.Clear;
    end;
    

    如果析构函数只影响父类型的字段,则无需重写析构函数。在您的情况下,TMyTreeNode.Destroy 仅从父级释放 NodeData,因此您不妨在TTreeNode&lt;T&gt;.FreeChildNodes 过程中执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-12
      • 2015-05-15
      • 2018-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多