您正在调用无参构造函数
TObjectList<T>
,实际上这是
TObjectList<T>
的父类
TList<T>
的构造函数。
TObjectList<T>
中声明的所有构造函数都接受名为
AOwnsObjects
的参数,该参数用于初始化
OwnsObjects
属性。因为您绕过了该构造函数,
OwnsObjects
默认为
False
,因此列表成员不会被销毁。
您应该确保调用初始化
OwnsObjects
的
TObjectList<T>
构造函数。例如:
{$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在实现多态行为时扮演着特殊角色。它可以出现在方法定义中,可以带或不带标识符。
如果inherited后面跟着成员的名称,则表示对属性、字段或普通方法的调用或引用,但是查找所引用的成员始于封闭方法类的直接祖先。例如,在以下情况下:
inherited Create(...);
在方法的定义中出现时,它会调用继承的Create。
当inherited后面没有标识符时,它指的是与封闭方法同名的继承方法,或者如果封闭方法是消息处理器,则指的是相同消息的继承消息处理器。在这种情况下,inherited不需要显式参数,但会将封闭方法调用时使用的相同参数传递给继承方法。例如:
inherited;
在构造函数的实现中经常出现。它使用传递给子类的相同参数调用继承的构造函数。
TObjectList<TPerson>
。除非你想要添加方法。 - David HeffernanTObjectList
的代码不会泄漏,但是如果我将TMembers
声明更改为TMembers = class(TObjectList<TPerson>)
,那么上面的代码就会显示内存泄漏。是的,我想要添加方法。我在这里展示的只是一个简单的虚构示例,希望能得到清晰的答案。 - alondono