Re: [fpc-pascal] Constructors & Destructors 101

2009-04-05 Thread Nikolay Nikolov

Jonas Maebe wrote:
If you had two different create constructors (for whatever reason), 
might you not also need two different destroy destructors?


No, the default destructor should always free all resources, 
regardless of how the class instance was created. Otherwise, it would 
also make your code more complex, because throughout the code you 
would have to track how the instance was created, so that in the end 
you could call the correct destructor.
I think there's something even more subtle than that. If a constructor 
blows up and raises an exception, the destructor Destroy is called 
automatically to clean up the partially created class, before the 
exception is handled. So, it's not just .free that is hardcoded to call 
destroy. IOW it is an extremely bad idea to have a destructor other than 
Destroy for classes and IMO shouldn't be allowed by the language. 
However, having multiple constructors is perfectly fine, as long as the 
destructor is only one.


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-04 Thread Bart
On 4/3/09, Doug Chamberlin  wrote:
>  Essentially, yes.
>
>  However, you may create subtle, lurking bugs if you omit that call and
> later refactor your code. For example, if you later change
>
>   type
> TFoo = class
>
>  to
>
>   type
> TFoo = class(TSomeClass)
>
>  and TSomeClass has some important work done in it's Create constructor. If
> you properly called "inherited Create;" now that important stuff will get
> done, just the way you want it to!
>

Despite the fact that I've been programming in Pascal and Delphi for
quite some time now, I've only recently started looking into and
writing components (thanks to Lazarus!).
Most tutorials on that topic started out with TComponent decendents,
where invoking the inherited contsructor is eminent.
I've since seen several TObjet derived classes, some of them invoking
inherited Create, some not. I never understood the difference and this
made me insecure wether my own (small) TObject derived classes (I
always invoked inherited Create in my constructor) were potentially
flawed.

>  
>  So, the big lesson here is to stick to the proper structure even though you
> may have outside knowledge that the form you should follow is not strictly
> necessary in all cases.
>  

I agree.

Thanks for clearing things up to me.

Bart
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-03 Thread Doug Chamberlin

Bart wrote:

On 4/3/09, Jonas Maebe  wrote:

 I think what is meant, is that if you create a direct subclass of TObject,
there is no need to call TObject's create constructor (e.g., via "inherited
create;") from your own constructors. It doesn't hurt if you do it of
course, and may be good practice to account for future situations where the
parent class may change.


I often wondered abou that.

So if i understand correctly:

Say I have

Type
  TFoo = class;
  private
fSomeField: Integer;
  public
constructor Create;
  end;

then

constructor  TFoo.Create
begin
  Inherited Create;
  fSomeField := -1;
end;

would in essence be equal to

constructor  TFoo.Create
begin
  fSomeField := -1;
end;

Since TOblect.Create "does nothing".


Essentially, yes.

However, you may create subtle, lurking bugs if you omit that call and 
later refactor your code. For example, if you later change


  type
TFoo = class

to

  type
TFoo = class(TSomeClass)

and TSomeClass has some important work done in it's Create constructor. 
If you properly called "inherited Create;" now that important stuff will 
get done, just the way you want it to!



So, the big lesson here is to stick to the proper structure even though 
you may have outside knowledge that the form you should follow is not 
strictly necessary in all cases.


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-03 Thread Jonas Maebe


On 03 Apr 2009, at 16:21, Bart wrote:


So if i understand correctly:

Say I have

Type
TFoo = class;
private
  fSomeField: Integer;
public
  constructor Create;
end;

then

constructor  TFoo.Create
begin
Inherited Create;
fSomeField := -1;
end;

would in essence be equal to

constructor  TFoo.Create
begin
fSomeField := -1;
end;

Since TOblect.Create "does nothing".


Yes.


Jonas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-03 Thread Bart
On 4/3/09, Jonas Maebe  wrote:
>  I think what is meant, is that if you create a direct subclass of TObject,
> there is no need to call TObject's create constructor (e.g., via "inherited
> create;") from your own constructors. It doesn't hurt if you do it of
> course, and may be good practice to account for future situations where the
> parent class may change.

I often wondered abou that.

So if i understand correctly:

Say I have

Type
  TFoo = class;
  private
fSomeField: Integer;
  public
constructor Create;
  end;

then

constructor  TFoo.Create
begin
  Inherited Create;
  fSomeField := -1;
end;

would in essence be equal to

constructor  TFoo.Create
begin
  fSomeField := -1;
end;

Since TOblect.Create "does nothing".

Bart
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-03 Thread Flávio Etrusco
> C) Just out of curiosity, am wondering why FreeAndNil is global procedure
> instead of a method/destructor of TObject.   I am guessing it is
> for compatibility with Delphi which may or may not have a reason?

A method could not act the way FreeAndNil works (zeroing a local
pointer variable). It could be a static/class method, but this would
just add noise to the code.
BTW FreeAndNil can only on TObject and descendants.

-Flávio
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-03 Thread Jonas Maebe


On 03 Apr 2009, at 03:43, Richard Ward wrote:


A)  The documentation says that for the create constructor:

(quote}
Description: Create creates a new instance of TObject. Currently it  
does nothing. It is also not virtual, so there is in principle no  
need to call it directly.

{unquote}

What is it meant by: "no need to call [create] directly?"  How do  
you invoke the constructor without calling it?


I think what is meant, is that if you create a direct subclass of  
TObject, there is no need to call TObject's create constructor (e.g.,  
via "inherited create;") from your own constructors. It doesn't hurt  
if you do it of course, and may be good practice to account for future  
situations where the parent class may change.



... and ... Why is create not virtual and the destroy destructor is?


Because when creating a class instance, you usually know the exact  
class type of that instance (e.g., TObject.create -> you know that the  
created instance type will be of the type TObject). This only changes  
if you use class reference types, but if you use those you can still  
declare your own virtual constructors.


Conversely, many routines that free a class instance, have no idea  
about the exact type of that instance (such as FreeAndNil: all it  
knows is that the instance inherits from TObject). So to make sure  
that all resources allocated by those class types are properly freed,  
the destructor almost has to be virtual (since otherwise, only  
TObject's dummy destructor would be called by, e.g., FreeAndNil).



B)  The documentation says that for the destroy destructor:

(quote}
Description: Destroy is the destructor of TObject. It will clean up  
the memory assigned to the instance. Descendent classes should  
override destroy if they want to do additional clean-up. No other  
destructor should be implemented.

{unquote}

What is it meant by: "No other destructor should be implemented?"


It means that you should not add "destructor  
my_peculiarly_named_destructor; virtual;" to your own classes. The  
reason is that TObject's free method, which is used by pretty much all  
code out there, is hardcoded to call "destroy". So if your destructor  
is named differently, a lot of existing code will not properly destroy  
instances of your class type.


...and...  Does it do "something" while the Create constructor  
doesn't?


No, TObject's default destructor does not do anything either.

If you had two different create constructors (for whatever reason),  
might you not also need two different destroy destructors?


No, the default destructor should always free all resources,  
regardless of how the class instance was created. Otherwise, it would  
also make your code more complex, because throughout the code you  
would have to track how the instance was created, so that in the end  
you could call the correct destructor.



What problems might you get into if you did?


See above.


Jonas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-03 Thread Jonas Maebe


On 03 Apr 2009, at 03:43, Richard Ward wrote:

5)	Although I can't remember reading it anywhere, I've noticed from  
my own demo programs that the addresses of objects are initially set  
to nil.


That is not correct. All global variables (classes/objects or not) are  
initialized to 0/nil, but local variables aren't (except in case of  
reference-counted types). Moreover, the contents of a class instance  
are also zeroed when creating it.



Jonas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-03 Thread Jonas Maebe


On 03 Apr 2009, at 03:43, Richard Ward wrote:

C)	Just out of curiosity, am wondering why FreeAndNil is global  
procedure instead of a method/destructor of TObject.


If you have:

var
  c: tsomeclass;
begin
  c:=c.tsomeclass.create;
  c.freeandnil
end;

then freeandnil would get, as first (hidden) parameter, the self  
pointer. However, this self pointer is a value parameter. So it would  
only contain the value of "c", not its address. Hence, there is no way  
to set "c" to nil inside the freeandnil method (while setting the  
instance variable to nil is the entire reason for using freeandnil).



Jonas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Constructors & Destructors 101

2009-04-03 Thread leledumbo

> What is it meant by: "no need to call [create] directly?"  How do you  
> invoke the constructor without calling it?  ... and ... Why is create  
> not virtual and the destroy destructor is?
Often in other OOP language, you need to call parent constructor before
doing anything else. In OP case,  you don't since it doesn't do anything.
Create isn't virtual because, as stated before, it doesn't do anything
therefore no relation with descendant constructor(s) needed. Destroy is
because it does "soemthing" (read below).

> What is it meant by: "No other destructor should be  
> implemented?"  ...and...  Does it do "something" while the Create  
> constructor doesn't?
No other destructor should be implemented if you don't need to do any
additional cleanup. It does "something", that is freeing memory assigned for
the instance while create doesn't do anything.

> If you had two different create constructors (for whatever reason),  
> might you not also need two different destroy destructors?   What  
> problems might you get into if you did?
Only if it needs two different way to cleanup. No problems if you did, I
often have overloaded constructors in classes I made (which of course only
calls the one with most arguments).

> Just out of curiosity, am wondering why FreeAndNil is global  
> procedure instead of a method/destructor of TObject.   I am guessing  
> it is for compatibility with Delphi which may or may not have a reason?
It is indeed for Delphi compatibility. Other possible reason: It can be used
by non-class types (i.e. Pointers) that do heap allocation.
-- 
View this message in context: 
http://www.nabble.com/Constructors---Destructors-101-tp22860474p22864567.html
Sent from the Free Pascal - General mailing list archive at Nabble.com.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal