调用TObjectList.Clear时,不会释放TObjectList中的对象



请参阅下面的代码。为了简单起见,我删除了很多代码,但剩下的代码仍然很长,对不起:(

IObserver = interface
['{1DD212F8-BD5E-47BF-9A3B-39EF7B9D99B5}']
procedure Update(Observable: IObservable);
end;
TObserver = class abstract (TSingletonImplementation, IObserver)
strict protected
//...
public
constructor Create;
destructor Destroy; virtual;
//IObserver
procedure Update(Observable: IObservable); virtual; abstract;
//... 
end;
TShapeModification = class abstract (TObserver)
strict protected
//...
public
//Doesn't have a constructor
end;
TRangePointModification = class(TShapeModification)
strict private
//...
public
constructor Create(...);
//...
end;
constructor TRangePointModification.Create(...);
begin
inherited Create;
//...
end;

然后在某个时刻:

TClientClass = class
strict private
fList: TObjectList<TShapeModification>;
public
constructor Create();
destructor Destroy(); override;
procedure Add(ShapeModification: TShapeModification);
end;
constructor TClientClass.Create;
begin
Self.fList:=TObjectList<TShapeModification>.Create(true);
end;
destructor TClientClass.Destroy;
begin
Self.fList.Clear;
FreeAndNil(Self.fList);
end;

最后,在某个时刻:

var
MyClient: TClientClass;
begin
MyClient:=TClientClass.Create();
MyClient.Add(TRangePointModification.Create());
MyClient.Free;
end;

当释放MyClient时,调用TClientClass析构函数,然后应该清除内部fList,但不调用TRangePointModification(来自TObserver(的析构函数为什么不呢

(我使用的是Delphi 10.2 Tokyo(

查看警告-编译器告诉什么是错误的:

W1010 Method 'Destroy' hides virtual method of base type ...

始终将override放在析构函数上(而不是虚拟的!(,否则对Free的调用将不会执行您放入其中的代码。

因此,作为一个基本建议:

  1. 总是编写零警告或提示的代码-它们很可能指向您迟早会遇到的缺陷

  2. 在您怀疑有缺陷的代码中设置断点-即使忽略编译器警告,您也会看到对Clear的调用从未进行

最新更新