德尔福发布接口指针

问题描述:

我在德尔福的接口挣扎。这个问题可能是微不足道的,但我是Delphi的新手,所以请原谅。我有一个TreeView的自定义节点,其中包含一个对象的接口(本质上,就像这里提出的:Storing interface pointer inside tree view nodes)。德尔福发布接口指针

问题是,一旦我删除了一个节点(为了重画树形视图)并将接口变量设置为零(释放不会出于某些原因,接口出于某种原因,我还没有完全理解),最奇怪的事情发生:

在我的对象,它包含一个列表,一个整数和一个字符串变量,字符串和列表将设置为空,而整数保持不变。

我无法解释这一点。有没有人知道解决方法,或者这种行为的可能原因?顺便说一下,我使用Delphi 10.2东京。

这是我相当引人注意的破坏方法:

myNode.destroy; 
begin 
    intf:= nil;// intf holds the interface to the object 
end; 

编辑:这是我的代码的简化版本:

我所指的对象:(我有一个看起来像几个类似的类OBJ但略有不同,我不知道哪一个将被存储在接口方面,但都具备这些变量)

Obj = class(InterfacedObject, IMyinterface) 
    count: integer; //this remains the same 
    children: array of ChildObj; //this will be emptied 
    name: string; //this will be set to '' 
    procedure addChild; 
    procedure IMyInterface.add = addChild; 
end; 

我定制treeNode节点:

MyNode = class(TTreeNode) 
    Intf: IMyinterface; 
    destructor destroy; override; 
end; 

在我的班级管理的TreeView:

MyForm.ReloadTree; 
begin 
    if myTreeView.Items.Count > 0 then 
    begin 
    myTreeView.Items.Clear; 
    end 
    for I:= 0 to RootObj.Count-1 do 
    begin 
    myTreeView.Items.AddChild(MyTreeview.Items[0], RootObj.Children[i].name); 
    (myTreeView.Items[0][i] as MyNode).Intf := Intf(RootObj.Children[i]); 
    //I will proceed iterating over all children and their children, doing 
    //the same process, a level higher in the treeView 
    //... 
    end; 
end; 
+0

哦,我的目标是根本不改变对象,因为我仍然需要它 – zink

+0

只需删除节点。内部数据在“TTreeNode”析构函数中(至少在VCL中)被“剔除”。这应该递减接口对象的引用计数并将其释放。 – Victoria

+0

感谢您的快速回复:)我尝试过,但结果是一样的。我想,如果我重写析构函数,无论内部发生什么,导致这种行为可能不会发生。但它确实 – zink

在我的对象,其中包含一个列表,整数,字符串变量,字符串和列表将被设置为空

,而整数保持不变。

这是完全正常的行为。字符串和接口是编译器管理的类型。整数不是。当一个对象被破坏时,编译器管理的数据成员会根据需要被自动释放,在字符串和接口的情况下,这些成员会涉及到指向其引用数据的指针。包含对象本身并未完全清零,因此非托管类型(如整数)在内存中不会被覆盖。

现在,这就是说,我看到您的ReloadTree()过程中的一些错误。

  1. for循环超过上限RootObj.Children[]名单。

  2. 当致电AddChild()时,第二个参数是string。您在该参数中传递RootObj.Children[i]。但是,在下一个语句中,您在分配MyNode.Intf字段时正在为接口键入相同的RootObj.Children[i]值。 A string不是接口。那么,RootObj.Children[]包含什么字符串或接口?

  3. 当分配MyNode.Intf字段时,您始终访问TreeView中的第一个节点,而不是新添加的节点。

+0

谢谢,这解释了为什么会发生。无论如何,我可以在销毁界面时防止“清零”。 – zink

+0

@zink不,你为什么要吗?你到底想要解决什么问题? –

+0

哦,是的,你是对的错误,我很抱歉,我没有我的代码可用,所以我只是很快重新输入我所知道的记忆。实际的代码可以避免所有这些问题:) – zink