i have a class based on TInterfacedObject. i add it to TTreeNode's Data property.
我有一个基于TInterfacedObject的类。我将它添加到TTreeNode的数据属性中。
TFacilityTreeItem=class(TInterfacedObject)
private
m_guidItem:TGUID;
m_SomeOtherNode:TTreeNode;
public
end;
i create many instances of this object & had assumed that because they're reference counted, i shouldn't need to Free them. that'd be handy.
我创建了这个对象的许多实例,并假定它们是引用计数的,所以我不需要释放它们。这很方便的。
however, when checking this, i turned on ReportMemoryLeaksOnShutdown and found they're not being freed after all.
然而,当我检查这个时,我打开了ReportMemoryLeaksOnShutdown,发现它们并没有被释放。
these objects are being created in a frame that's placed on the main form. in the main form's FormClose, i clear the tree nodes such that every object should be freed.
这些对象是在一个放在主窗体上的框架中创建的。在主表单的FormClose中,我清除了树节点,这样每个对象都应该被释放。
what's happening?
发生什么事情了?
thank you for your help!
谢谢你的帮助!
3 个解决方案
#1
16
TInterfacedObject itself is not reference counted, only interfaces are. You can implement interfaces using TInterfacedObject which basically saves you the effort of implementing the reference counting methods yourself. Unfortunately it still will not work in your case: The compiler does not know that you are assigning interfaces to the TTreeNode.Data property since it is not declared as an interface but as a pointer. So all kinds of weird things will happen:
TInterfacedObject本身不是引用计数,只有接口是。您可以使用TInterfacedObject实现接口,这基本上可以节省您自己实现引用计数方法的工作量。不幸的是,它仍然不能在您的情况下工作:编译器不知道您正在为TTreeNode分配接口。数据属性,因为它不是作为一个接口声明的,而是作为一个指针。所以各种奇怪的事情都会发生:
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
As soon as you try to access your object through the .Data property, you will get an access violation.
当您试图通过. data属性访问您的对象时,您将获得访问违背。
So, don't bother with interfaces in this case, you could get it to work, but it will be much more effort than it is worth.
所以,在这种情况下,不要使用接口,您可以让它工作,但是它将比它的价值更努力。
#2
3
You should declare the Field/Variable as Interface
您应该将字段/变量声明为接口。
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;
To access your fields, you should declare properties in IFacilityTreeItem Interface, with Getters and Setters.
要访问您的字段,您应该在iservictytreeitem接口中声明属性,并使用getter和setter。
#3
2
As dummzeuch said, you can get this to work with interfaces, but it takes some more code since the Data property of a TTreeNode is a pointer. For anyone wondering how to do that, this link has an example of how to do it for TListItem (it's pretty much the same for TTreeNode). You may also find it useful to read the section about interfaces and subsequent section about reference counting on that page.
正如dummzeuch所说,您可以让它与接口一起工作,但是它需要更多的代码,因为TTreeNode的数据属性是一个指针。对于任何想知道如何做到这一点的人来说,这个链接有一个关于如何为TListItem做它的例子(对于TTreeNode来说几乎是一样的)。您可能还会发现,阅读关于该页面上引用计数的有关接口和后续部分的章节是有用的。
#1
16
TInterfacedObject itself is not reference counted, only interfaces are. You can implement interfaces using TInterfacedObject which basically saves you the effort of implementing the reference counting methods yourself. Unfortunately it still will not work in your case: The compiler does not know that you are assigning interfaces to the TTreeNode.Data property since it is not declared as an interface but as a pointer. So all kinds of weird things will happen:
TInterfacedObject本身不是引用计数,只有接口是。您可以使用TInterfacedObject实现接口,这基本上可以节省您自己实现引用计数方法的工作量。不幸的是,它仍然不能在您的情况下工作:编译器不知道您正在为TTreeNode分配接口。数据属性,因为它不是作为一个接口声明的,而是作为一个指针。所以各种奇怪的事情都会发生:
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
As soon as you try to access your object through the .Data property, you will get an access violation.
当您试图通过. data属性访问您的对象时,您将获得访问违背。
So, don't bother with interfaces in this case, you could get it to work, but it will be much more effort than it is worth.
所以,在这种情况下,不要使用接口,您可以让它工作,但是它将比它的价值更努力。
#2
3
You should declare the Field/Variable as Interface
您应该将字段/变量声明为接口。
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;
To access your fields, you should declare properties in IFacilityTreeItem Interface, with Getters and Setters.
要访问您的字段,您应该在iservictytreeitem接口中声明属性,并使用getter和setter。
#3
2
As dummzeuch said, you can get this to work with interfaces, but it takes some more code since the Data property of a TTreeNode is a pointer. For anyone wondering how to do that, this link has an example of how to do it for TListItem (it's pretty much the same for TTreeNode). You may also find it useful to read the section about interfaces and subsequent section about reference counting on that page.
正如dummzeuch所说,您可以让它与接口一起工作,但是它需要更多的代码,因为TTreeNode的数据属性是一个指针。对于任何想知道如何做到这一点的人来说,这个链接有一个关于如何为TListItem做它的例子(对于TTreeNode来说几乎是一样的)。您可能还会发现,阅读关于该页面上引用计数的有关接口和后续部分的章节是有用的。