2017-09-23 100 views
-3

我在德爾福的接口掙扎。這個問題可能是微不足道的,但我是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

回答

0
在我的對象,其中包含一個列表,整數,字符串變量,字符串和列表將被設置爲空

,而整數保持不變。

這是完全正常的行爲。字符串和接口是編譯器管理的類型。整數不是。當一個對象被破壞時,編譯器管理的數據成員會根據需要被自動釋放,在字符串和接口的情況下,這些成員會涉及到指向其引用數據的指針。包含對象本身並未完全清零,因此非託管類型(如整數)在內存中不會被覆蓋。

現在,這就是說,我看到您的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