oopdelphidelphi-xe6

Free an object through calling destroy method of ancestor class


I have multiple descendent classes sharing an ancestor. When I want to destroy an object I don't know what the actual type is, because the pointer holding the actual object has an ancestor type.

Thinks of it like you have multiple descendent from TButton, saving all objects in an array of type TButton, now when you want to destroy the objects, calling TButton(ButtonArray[I]).Destroy cause memory leaks, because it didn't call Destroy method of descendent types.

I want an approach to properly destroy descendent classes from the ancestor Destroy method.


Solution

  • This problem doesn't exist.

    Since the destructor Destroy is a virtual method, the correct one will be chosen automatically at run-time, because Delphi knows the actual class of every object instance, no matter what kind of pointers you have to it in your source code. (Indeed, try ShowMessage(MyObj.ClassName).)

    For example, given TFruit, TApple = class(TFruit), and TBanana = class(TFruit) and

    var
      a, b: TFruit;
    begin
      a := TApple.Create;
      b := TBanana.Create;
      a.Destroy; // calls TApple.Destroy, if properly overridden
      b.Destroy; // calls TBanana.Destroy, if properly overridden
    end;
    

    (except that, of course, you never write x.Destroy but x.Free).

    So why doesn't this work for you? Well, this is a common mistake:

    TChild = class(TParent)
      constructor Create;
      destructor Destroy;
    end;
    

    must be

    TChild = class(TParent)
      constructor Create;
      destructor Destroy; override; // <-- Add override!
    end;
    

    Otherwise you will not override TParent.Destroy, but simply introduce a new destructor with the same name.

    Actually, the compiler tries to warn you about this:

    [dcc32 Warning] W1010 Method 'Destroy' hides virtual method of base type 'TObject'
    

    or something like that.