Reputation: 1800
SITUATION
I am studying Delphi from Marco Cantu's book and I already have experience with OOP because I usually work with Java and PHP. To better understand what I'm reading I've made this test:
type
TFraction = class
private
number: double;
num, den: integer;
fraction: string;
function hcf(x: integer; y: integer): integer;
public
constructor Create(numerator: integer; denominator: integer); overload;
constructor Create(value: string); overload;
function getFraction: string;
end;
This is a super easy class that converts a decimal number into a fraction. I'm not including the other parts of the code where I define constructors and functions since they aren't useful for my question. I am creating the object in this way.
var a: TFraction;
begin
a := TFraction.Create(225, 35);
ShowMessage(a.getFraction);
//The output of ^ is 45/7
a.Free;
end;
QUESTION
From what I've learnt, I know that I have to get rid of the object once I've used it and in fact I am using the Free
. In this way I free the memory and I avoid memory leaks.
By the way I see that I also have the possibility to override a destructor
. I don't understand very well the behavior of the Free
and the Destroy
. I use the Free
when I have to get rid of an object that I don't need anymore. When I override a destructor I can free the object and also make other actions?
In short, when is it good to use the Free? And when should I prefer the Destroy?
Upvotes: 4
Views: 2944
Reputation: 27296
In general, the destructor is used if you need to do something during object destruction which otherwise wouldn't be done automatically. Like freeing memory that you initialize in the constructor. In your example, there is no need to override the destructor, since (presumably) you don't create anything which needs to be destroyed manually.
Also, keep in mind that Destroy
is not intended to be called by you at all - neither internally or externally. Free
automatically takes care of calling that for you - with a little extra work going on. Free
checks if the object is nil
or not, and only calls Destroy
if it's not nil
.
Take this for example:
type
TMyObject = class(TObject)
private
FSomeOtherObject: TSomeOtherObject;
public
constructor Create;
destructor Destroy; override;
end;
constructor TMyObject.Create;
begin
inherited;
FSomeOtherObject:= TSomeOtherObject.Create;
end;
destructor TMyObject.Destroy;
begin
FSomeOtherObject.Free;
inherited;
end;
Just as an added note, the usage I see above is missing something. What if the code between Create
and Free
raises some exception? The procedure would exit, and it would never be free'd. So instead, you should use a try / finally
block...
a := TFraction.Create(225, 35);
try
ShowMessage(a.getFraction);
finally
a.Free;
end;
This would ensure that no matter what happens between try
and finally
, the code between finally
and end
will always be called.
Upvotes: 7
Reputation: 598089
By the way I see that I also have the possibility to override a
destructor
. I don't understand very well the behavior of theFree
and theDestroy
.
Free()
calls the destructor if the object pointer is not nil.
Destroy()
is the actual destructor.
I use the
Free
when I have to get rid of an object that I don't need anymore. When I override a destructor I can free the object and also make other actions?
Yes. The destructor is called when the object is in the process of being destroyed. Overriding the destructor is a good place to perform cleanup actions related to the object that is being destroyed.
In short, when is it good to use the Free? And when should I prefer the Destroy?
You can call Destroy()
directly, but it is generally preferred to call Free()
instead and let it call Destroy()
for you.
Upvotes: 3