Ответ 1
Вы вызываете конструктор без параметров TObjectList<T>
. На самом деле это конструктор TList<T>
, из которого выведен класс TObjectList<T>
.
Все конструкторы, объявленные в TObjectList<T>
, принимают параметр с именем AOwnsObjects
, который используется для инициализации свойства OwnsObjects
. Поскольку вы обходите этот конструктор, OwnsObjects
по умолчанию имеет значение False
, а члены списка не уничтожаются.
Вы должны убедиться, что вы вызываете конструктор TObjectList<T>
, который инициализирует OwnsObjects
. Например:
{$APPTYPE CONSOLE}
uses
System.Generics.Collections;
type
TDerivedGenericObjectList = class(TObjectList<TObject>)
public
constructor Create;
end;
constructor TDerivedGenericObjectList.Create;
begin
inherited Create(True);
end;
var
List: TDerivedGenericObjectList;
begin
ReportMemoryLeaksOnShutdown := True;
List := TDerivedGenericObjectList.Create;
List.Add(TObject.Create);
List.Free;
end.
Возможно, лучшим вариантом было бы сделать ваш конструктор также предлагающим параметр AOwnsObjects
:
type
TDerivedGenericObjectList = class(TObjectList<TObject>)
public
constructor Create(AOwnsObjects: Boolean = True);
end;
constructor TDerivedGenericObjectList.Create(AOwnsObjects: Boolean);
begin
inherited Create(AOwnsObjects);
end;
Или:
type
TDerivedGenericObjectList = class(TObjectList<TObject>)
public
constructor Create(AOwnsObjects: Boolean = True);
end;
constructor TDerivedGenericObjectList.Create(AOwnsObjects: Boolean);
begin
inherited;
end;
Итак, вы можете удивиться, почему исходная версия выбрала конструктор TList<T>
, а не один в TObjectList<T>
. Хорошо, посмотрим на это более подробно. Вот ваш код еще раз:
type
TDerivedGenericObjectList = class(TObjectList<TObject>)
public
constructor Create;
end;
constructor TDerivedGenericObjectList.Create;
begin
inherited;
end;
Когда inherited
используется таким образом, компилятор ищет конструктор с той же самой сигнатурой, что и этот. Он не может найти его в TObjectList<T>
, потому что у всех есть параметр. Он может найти один в TList<T>
, и тот, который он использует.
Как вы отмечаете в комментариях, следующий вариант не течет:
constructor TDerivedGenericObjectList.Create;
begin
inherited Create;
end;
Этот синтаксис, в отличие от голого inherited
, найдет методы, которые совпадают при замене параметров по умолчанию. И поэтому вызывается единственный конструктор параметров TObjectList<T>
.
документация содержит следующую информацию:
Заданное слово, унаследованное, играет особую роль в реализации полиморфного поведения. Это может произойти в определениях методов с идентификатором или без него.
Если для унаследованного следует имя члена, он представляет собой вызов нормального метода или ссылку на свойство или поле, за исключением того, что поиск ссылочного элемента начинается с непосредственного предка класса вмещающего метода. Например, когда:
inherited Create(...);
возникает в определении метода, он вызывает унаследованный Create.
Когда унаследованный не имеет идентификатора после него, он относится к унаследованному методу с тем же именем, что и метод-оболочка, или, если метод-окружение является обработчиком сообщений, унаследованному обработчику сообщений для того же сообщения. В этом случае унаследованный не принимает явных параметров, но передает унаследованному методу те же параметры, с которыми был вызван метод окружения. Например:
inherited;
часто встречается при реализации конструкторов. Он вызывает унаследованный конструктор с теми же параметрами, которые были переданы потомку.