gpt4 book ai didi

delphi - 如何继承TObjectList而不是继承TObjectList

转载 作者:行者123 更新时间:2023-12-03 14:40:01 24 4
gpt4 key购买 nike

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

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

最佳答案

您正在调用 TObjectList<T> 的无参数构造函数。这实际上是 TList<T> 的构造函数,来自 TObjectList<T> 的类(class)是衍生出来的。

TObjectList<T> 中声明的所有构造函数接受名为 AOwnsObjects 的参数用于初始化 OwnsObjects属性(property)。因为您正在绕过该构造函数,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> 的单参数构造函数叫做。

documentation有以下信息:

The reserved word inherited plays a special role in implementing polymorphic behavior. It can occur in method definitions, with or without an identifier after it.

If inherited is followed by the name of a member, it represents a normal method call or reference to a property or field, except that the search for the referenced member begins with the immediate ancestor of the enclosing method's class. For example, when:

inherited Create(...);

occurs in the definition of a method, it calls the inherited Create.

When inherited has no identifier after it, it refers to the inherited method with the same name as the enclosing method or, if the enclosing method is a message handler, to the inherited message handler for the same message. In this case, inherited takes no explicit parameters, but passes to the inherited method the same parameters with which the enclosing method was called. For example:

inherited;

occurs frequently in the implementation of constructors. It calls the inherited constructor with the same parameters that were passed to the descendant.

关于delphi - 如何继承TObjectList<T>而不是继承TObjectList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32578436/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com