4

TInterfacedObjectに基づくクラスがあります。TTreeNodeのDataプロパティに追加します。

TFacilityTreeItem=class(TInterfacedObject)
private
  m_guidItem:TGUID;
  m_SomeOtherNode:TTreeNode;
public
end;

私はこのオブジェクトの多くのインスタンスを作成し、それらは参照カウントであるため、それらを解放する必要はないと想定していました。それは便利でしょう。

ただし、これを確認すると、ReportMemoryLeaksOnShutdownをオンにしたところ、結局解放されていないことがわかりました。

これらのオブジェクトは、メインフォームに配置されたフレームに作成されています。メインフォームのFormCloseで、すべてのオブジェクトが解放されるようにツリーノードをクリアします。

何が起こっていますか?

ご協力ありがとうございました!

4

3 に答える 3

16

TInterfacedObject 自体は参照カウントされず、インターフェイスのみがカウントされます。TInterfacedObject を使用してインターフェイスを実装できます。これにより、参照カウント メソッドを自分で実装する労力を基本的に節約できます。残念ながら、あなたの場合はまだ機能しません。TTreeNode.Data プロパティはインターフェイスとしてではなくポインターとして宣言されているため、コンパイラーはインターフェイスを TTreeNode.Data プロパティに割り当てていることを知りません。したがって、あらゆる種類の奇妙なことが起こります。

MyInt := TFacilityTreeItem.Create; // ref count = 1
// Node.Data := MyInt; // won't compile
Node.Data := pointer(MyInt); // no interface assignment, ref count stays 1
...
end; // ref count reaches 0, your object gets freed

.Data プロパティを介してオブジェクトにアクセスしようとするとすぐに、アクセス違反が発生します。

したがって、この場合はインターフェースを気にしないでください。機能させることはできますが、価値があるよりもはるかに多くの労力が必要になります。

于 2009-01-27T20:15:33.163 に答える
3

フィールド/変数をインターフェースとして宣言する必要があります

IFacilityTreeItem = IInterface
end;

TFacilityTreeItem=class(TInterfacedObject, IFacilityTreeItem)
private
  m_guidItem:TGUID;
  m_SomeOtherNode:TTreeNode;
end;

var
  Item: IFacilityTreeItem; // Variable as Interface
begin
  Item:= TFacilityTreeItem.Create;
...
end;

フィールドにアクセスするには、ゲッターとセッターを使用して、IFacilityTreeItemインターフェイスでプロパティを宣言する必要があります。

于 2009-01-27T21:28:39.053 に答える
2

dummzeuch が言ったように、これをインターフェイスで動作させることができますが、TTreeNode の Data プロパティはポインターであるため、もう少しコードが必要です。それを行う方法を知りたい人のために、このリンクには TListItem でそれを行う方法の例があります (TTreeNode の場合とほとんど同じです)。また、そのページのインターフェースに関するセクションと参照カウントに関する後続のセクションを読むと役立つ場合があります。

于 2009-02-17T06:55:39.037 に答える