当调用TObjectList.Clear

时间:2018-07-23 09:57:13

标签: delphi

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

  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的析构函数(来自{{1} })不被调用。 为什么不呢?

(我正在使用Delphi 10.2 Tokyo)

1 个答案:

答案 0 :(得分:14)

查看警告-编译器会告诉您什么地方出错了:

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

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

因此,作为基本建议:

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

  2. 将断点放入您怀疑有缺陷的代码中-即使忽略编译器警告,您甚至都不会调用Clear