Вопрос

у меня есть класс, основанный на TInterfacedObject .я добавляю его в свойство данных TTreeNode .

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

Как только вы попытаетесь получить доступ к своему объекту через .Свойство Data, вы получите сообщение о нарушении доступа.

Так что не беспокойтесь об интерфейсах в этом случае, вы могли бы заставить его работать, но это потребует гораздо больше усилий, чем оно того стоит.

Другие советы

Вы должны объявить Поле / переменную как Интерфейс

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 с помощью Getters и Setters .

Как думмзеух сказал, вы можете заставить это работать с интерфейсами, но для этого требуется еще немного кода, поскольку свойство Data TTreeNode является указателем.Для тех, кому интересно, как это сделать, эта ссылка есть пример того, как это сделать для TListItem (это почти то же самое для TTreeNode).Вам также может оказаться полезным прочитать раздел о интерфейсы и последующий раздел о подсчете ссылок на этой странице.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top