Объекты Delphi всегда должны «принадлежать» другому объекту, а объект-владелец отвечает за освобождение принадлежащего объекта при вызове его Destructor. Так как это делается для каждого класса, не должно быть никаких проблем. Вы могли бы использовать RTTI для этого, но это было бы тратой времени и ресурсов, поскольку писать деструкторы очень просто.
Например, базовый класс вводит два поля типа TObject:
TBaseClass = class
private
public
OwnedObject: TObject;
NotOwnedObject: TObject;
destructor Destroy;override;
end;
destructor TBaseClass.Destroy;override;
begin
OwnedObject.Free; // TBaseClass owns this object, it should be destroyed when
// TBaseClass is destroyed.
// Do NOT call NotOwnedObject.Free: that object is not owned by TBaseClass,
// a different object is responsible for calling Free on it.
// ALWAYS call "inherited" from your destructor, it allows daisy-chaining destructors.
// more on this in the next example.
inherited;
end;
Классы-потомки, которые вводят новые поля, должны переопределить деструктор и освободить эти объекты, затем вызвать inherited
, чтобы дать родителю шанс освободить введенные им объекты. Пример:
TFirstClass = class(TBaseClass)
public
AnOtherOwnedObject: TObject;
AnOtherNotOwnedObject: TObject;
destructor Destroy;override;
end;
destructor TFirstClass.Destroy;override;
begin
// Free the stuff we owned and *we* introduced:
AnOtherOwnedObject.Free;
// Call the inherited destructor so the base class can free fields they introduced:
inherited;
end;
В своем вопросе вы говорите:
Мне нужно реализовать DESTRUCTOR, который мог бы найти все поля (типа объекта) из одного базового класса и предоставить Free для него, чтобы избежать всех этих утечек памяти.
Как видите, это не способ сделать это: деструктор производного класса вызывает inherited
, поэтому базовый класс получает шанс освободить введенные поля.
- Как говорит Барри Келли, вам не нужно проверять
nil
перед вызовом .Free
, потому что Free делает это сам.
- Как говорит Дэвид Хеффернан, все, что вам нужно сделать, это следовать этой схеме везде, и у вас все будет хорошо, никаких утечек памяти. Так VCL всегда работал!
- Как говорит mjn, обратите внимание, чтобы не переопределять принадлежащие объекты другими объектами, не освобождая их: когда вы делаете это, вы теряете последнюю ссылку на старый объект и больше не можете его освободить, это гарантированная утечка памяти.