为什么不TInterfacedObject垃圾收集的后裔?
-
20-08-2019 - |
题
我有基于TInterfacedObject的类。我将其添加到TTreeNode的Data属性。
TFacilityTreeItem=class(TInterfacedObject)
private
m_guidItem:TGUID;
m_SomeOtherNode:TTreeNode;
public
end;
我创建这个对象的多个实例与曾以为,因为他们是引用计数的,我不应该需要释放他们。那会是方便的。
然而,这个检查的时候,我打开ReportMemoryLeaksOnShutdown,发现他们没有被释放后所有。
正在在,将其放置在主窗体上的帧创建的这些对象。在主窗体的FormClose,我清除树节点,使得每个对象应该被释放。
发生了什么?
感谢您的帮助!
解决方案
TInterfacedObject本身不被参考计数,只接口。您可以实现使用TInterfacedObject基本上可以节省您实现自己的引用计数方法的努力接口。遗憾的是它仍然不会工作你的情况:编译器不知道你是分配给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
只要你尝试过。数据属性访问你的对象,你会得到一个访问冲突。
所以,不要在这种情况下接口打扰,你可以得到它的工作,但它会更多的努力比它的价值。
其他提示
您应该声明的字段/变量作为接口
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接口声明属性,与getter和setter。
由于 dummzeuch说,你可以得到这与接口的工作,但它需要更多的代码,因为一个TTreeNode数据属性是一个指针。对于任何人想知道如何做到这一点,此链接有一个例子如何做到这一点的TListItem(这是相当多的TTreeNode相同)。您也可以找到有用的信息有关接口和后续的部分关于在该网页上的参考计数部。
不隶属于 StackOverflow