Domanda

Ho una classe basata su TInterfacedObject. lo aggiungo alla proprietà Data di TTreeNode.

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

creo molte istanze di questo oggetto & amp; avevo ipotizzato che, poiché sono contati i riferimenti, non avrei dovuto liberarli. sarebbe utile.

tuttavia, quando ho controllato questo, ho attivato ReportMemoryLeaksOnShutdown e ho scoperto che dopo tutto non venivano liberati.

questi oggetti vengono creati in una cornice posizionata nel modulo principale. nel FormClose del modulo principale, deseleziono i nodi dell'albero in modo che ogni oggetto debba essere liberato.

cosa sta succedendo?

grazie per il tuo aiuto!

È stato utile?

Soluzione

TInterfacedObject stesso non viene conteggiato come riferimento, lo sono solo le interfacce. Puoi implementare interfacce usando TInterfacedObject che sostanzialmente ti risparmia lo sforzo di implementare tu stesso i metodi di conteggio dei riferimenti. Sfortunatamente non funzionerà nel tuo caso: il compilatore non sa che stai assegnando interfacce alla proprietà TTreeNode.Data poiché non è dichiarata come interfaccia ma come puntatore. Quindi accadranno tutti i tipi di cose strane:

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

Non appena provi ad accedere al tuo oggetto tramite la proprietà .Data, otterrai una violazione di accesso.

Quindi, in questo caso, non preoccuparti delle interfacce, potresti farlo funzionare, ma sarà molto più sforzo di quanto valga la pena.

Altri suggerimenti

Dovresti dichiarare il campo / la variabile come interfaccia

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;

Per accedere ai campi, è necessario dichiarare le proprietà nell'interfaccia IFacilityTreeItem, con Getter e setter.

Come dummzeuch ha detto , puoi ottenere questo per funzionare con le interfacce, ma richiede un po 'più di codice poiché la proprietà Data di un TTreeNode è un puntatore. Per chiunque si chieda come farlo, questo link ha un esempio di come farlo per TListItem (è praticamente lo stesso per TTreeNode). Potresti anche trovare utile leggere la sezione sulle interfacce e successive sezione sul conteggio dei riferimenti in quella pagina.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top