简体   繁体   中英

Delphi Cast: Memory leak?

In Delphi, I'm casting an inherited class from a base class which is already created. I believe this shares the base class addresses between the two classes, but the inherited's class's extra members get extra memory allocated to them, but are not initialised.

If the shared base class is then freed, does this cause a memory leak for the Inherited's class's members?

If so, what is the best way to clean up the inherited classes members if I want to leave the base class untouched?

program Project1;

uses
  SysUtils;

type
   TBase = class(TObject)
   public
     basemember : string ;
     Constructor Create() ;
   end;

   TInherited = class(TBase)
   public
     inheritedmember : string ;
     Constructor Create() ;
   end ;

   Constructor TBase.Create() ;
   begin
       basemember := 'Basemember' ;
       Writeln ('basemember') ;
   end ;

   Constructor TInherited.Create() ;
   begin
       inheritedmember := 'inheritedmember' ;
       Writeln ('inheritedmember') ;
   end ;

var
     baseclass      : TBase;
     castbaseclass  : TInherited;
begin

  Writeln ('Base Class');
  baseclass := TBase.Create();

  Writeln ('');
  Writeln ('Cast Inherited Class');
  castbaseclass := TInherited(baseclass);

  baseclass.Free; //memory leak?
  ReadLn;

end.

There is no memory leak here, but the cast is still wrong.

You are concerned about this line of code:

castbaseclass := TInherited(baseclass);

Since Delphi classes are reference types, baseclass and castbaseclass are both pointers. All you have done here is assigned a pointer variable. You never subsequently refer to castbaseclass . If you did do that, then there would be potential for runtime errors because the compiler believes that castbaseclass is a TInherited instance, but in fact it is an instance of a less specialized class, TBase .

However, you have a very deep misunderstanding.

I'm casting an inherited class from a base class which is already created. I believe this shares the base class addresses between the two classes, but the inherited's class's extra members get extra memory allocated to them, but are not initialised.

No! Absolutely not. In order to instantiate a TInherited instance you must call a constructor of TInherited . You cannot create an instance of one class and expect it to ever morph into another class. The type of an instance is determined once and for all when it is created. The memory for an instance is allocated when the instance is created, and at no other time.

So, if you want a TInherited , create one. If you want a TBase , create one. But you cannot create a TBase and change its type to be a TInherited . What you can do is create a TInherited and then assign it to a variable of type TBase . That's because TInherited is derived from TBase .

So you can write:

var
  base: TBase;
  inherited_: TInherited; // _ because inherited is a keyword
....
inherited_ := TInherited.Create;
base := inherited_;

But you cannot write:

var
  base: TBase;
  inherited_: TInherited;
....
base := TBase.Create;
inherited_ := base;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM