Delphi 如何从TObjectList继承<;T>;而不是从TObjectList继承

Delphi 如何从TObjectList继承<;T>;而不是从TObjectList继承,delphi,inheritance,generic-collections,Delphi,Inheritance,Generic Collections,为什么这个程序报告内存泄漏 {$APPTYPE CONSOLE} uses System.Generics.Collections; type TDerivedGenericObjectList = class(TObjectList<TObject>) public constructor Create; end; constructor TDerivedGenericObjectList.Create; begin inherited; end;

为什么这个程序报告内存泄漏

{$APPTYPE CONSOLE}

uses
  System.Generics.Collections;

type
  TDerivedGenericObjectList = class(TObjectList<TObject>)
  public
    constructor Create;
  end;

constructor TDerivedGenericObjectList.Create;
begin
  inherited;
end;

var
  List: TDerivedGenericObjectList;

begin
  ReportMemoryLeaksOnShutdown := True;
  List := TDerivedGenericObjectList.Create;
  List.Add(TObject.Create);
  List.Free;
end.
{$APPTYPE控制台}
使用
系统、泛型、集合;
类型
tDelivedGenericObjectList=类(TObjectList)
公众的
构造函数创建;
结束;
构造函数TDerivedGenericObjectList.Create;
开始
继承;
结束;
变量
列表:tDelivedGenericObject列表;
开始
ReportMemoryLeaksOnShutdown:=True;
列表:=TDerivedGenericObjectList.Create;
List.Add(TObject.Create);
列表。免费;
结束。

您可以使用泛型。它工作正常,没有类型转换和内存泄漏(
TObjectList
TObjectDictionary
列表根据空闲命令自动销毁内部对象)

一些提示:

  • TObjectList
    ——像
    membersList.free
    一样自动销毁免费人员列表

  • t列表
    ——不要销毁人员列表。您必须创建析构函数并手动释放列表中的每个人

下面是您的代码示例(使用新构造函数,无内存泄漏,并与旧代码向后兼容--请参见
GetPerson
):

类型
TPerson=类
公众的
名称:字符串;
年龄:整数;
功能副本:TPerson;
结束;
t成员=类(TObjectList)
私有的
函数GetPerson(i:Integer):TPerson;
公众的
property Person[i:Integer]:t Person读取GetPerson;
构造函数创建(SourceList:TMembers);超载;
结束;
{TPerson}
函数TPerson.Copy:TPerson;
变量
个人:TPerson,;
开始
person:=TPerson.Create;
person.Name:=Self.Name;
人.年龄:=自身.年龄;
结果:=人;
结束;
{t成员}
构造函数TMembers.Create(SourceList:TMembers);
变量
个人:TPerson,;
开始
继承创造;
对于SourceList中的人员,请执行以下操作:
开始
Self.Add(person.Copy);
结束;
结束;
函数TMembers.GetPerson(i:Integer):TPerson;
开始
结果:=Self[i];
结束;
程序t用于M21。按钮1单击(发件人:ToObject);
变量
个人:TPerson,;
成员1:t成员;
成员2:t成员;
开始
//测试代码
memsList1:=TMembers.Create;
person:=TPerson.Create;
人名:='Name 1';
人.年龄:25岁;;
成员列表1.添加(个人);
person:=TPerson.Create;
人名:=“姓名2”;
人.年龄:27岁;;
成员列表1.添加(个人);
memsList2:=TMembers.Create(memsList1);
ShowMessageFmt('mems 1计数=%d;mems 2计数=%d',[memsList1.count,memsList2.count]);
FreeAndNil(memsList1);
FreeAndNil(memsList2);
结束;

您正在调用
TObjectList
的无参数构造函数。这实际上是
TList
的构造函数,该类派生了
TObjectList

TObjectList
中声明的所有构造函数都接受名为
AOwnsObjects
的参数,该参数用于初始化
OwnsObjects
属性。因为您绕过了该构造函数,
OwnsObjects
默认为
False
,并且列表的成员不会被销毁

您应该确保调用初始化
OwnsObjects
TObjectList
构造函数。例如:

{$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.
或:

与继承的裸
相比,此语法将在替换默认参数时找到匹配的方法。因此调用了
TObjectList
的单参数构造函数

政府有以下资料:

继承的保留字在实现多态行为中起着特殊的作用。它可以出现在方法定义中,后面有或没有标识符

如果inherited后跟成员的名称,则表示对属性或字段的普通方法调用或引用,除非对被引用成员的搜索从封闭方法类的直接祖先开始。例如,当:

inherited Create(...);
发生在方法的定义中,它调用继承的Create

如果继承后没有标识符,则它引用与封闭方法同名的继承方法,或者,如果封闭方法是消息处理程序,则引用同一消息的继承消息处理程序。在这种情况下,inherited不接受显式参数,而是将调用封闭方法时使用的相同参数传递给inherited方法。例如:

inherited;
在构造函数的实现中经常发生。它使用传递给子体的相同参数调用继承的构造函数


重构会有所帮助。你的漏洞是因为你的代码有缺陷。我们无法看到您的代码。无论如何,为什么要使用子类呢。您可以直接使用
TObjectList
。除非你想添加方法。@DavidHeffernan我已经编辑了添加构造函数和用法的问题。带有
TObjectList
的代码不会泄漏。但是如果我将
TMembers
声明更改为
TMembers=class(TObjectList)
现在上面的代码显示内存泄漏。是的,我想给它添加一些方法。我在这里展示的只是一个简单的虚构的例子,希望是一个清晰的问题。我重新写了你的问题,让它问我相信你想问的,根据你的评论。而且,有了这个问题列表,我更容易回答!!;-)根据我的经验,这样一个简单完整的程序可以让回答更容易,而且它也能帮助你,因为它的重点是清晰和通畅的。你应该描述一下为什么没有memleaks。只有代码没有帮助理解。要启用内存泄漏报告,请添加
ReportMemoryLeaksOnShutdown:=True。初始化
。如果存在内存泄漏,则报告wil
type
  TDerivedGenericObjectList = class(TObjectList<TObject>)
  public
    constructor Create(AOwnsObjects: Boolean = True);
  end;

constructor TDerivedGenericObjectList.Create(AOwnsObjects: Boolean);
begin
  inherited;
end;
type
  TDerivedGenericObjectList = class(TObjectList<TObject>)
  public
    constructor Create;
  end;

constructor TDerivedGenericObjectList.Create;
begin
  inherited;
end;
constructor TDerivedGenericObjectList.Create;
begin
  inherited Create;
end;
inherited Create(...);
inherited;