[lazarus] Order of destruction in TCustomListBox

Marc Weustink marc.weustink at cuperus.nl
Mon Dec 15 08:06:56 EST 2003


+ From: michael at idefix.wisa.be [mailto:michael at idefix.wisa.be]On Behalf Of
+ Michael Van Canneyt
+ Sent: maandag 15 december 2003 13:49
+
+ On Mon, 15 Dec 2003, Micha Nelissen wrote:
+
+ > Michael Van Canneyt wrote:
+ > >
+ > > On Mon, 15 Dec 2003, Micha Nelissen wrote:
+ > >
+ > >
+ > >>Mattias Gaertner wrote:
+ > >>
+ > >>
+ > >>>On Sun, 14 Dec 2003 15:09:48 +0100  Micha Nelissen
+ > >>><micha at neli.hopto.org> wrote:
+ > >>>
+ > >>>><output>
+ > >>>>CB.SomeFunc call
+ > >>>>Constructor
+ > >>>></output>
+ > >>>>
+ > >>>>Which is not logical, IMHO.
+ > >>>
+ > >>>
+ > >>>It is just a matter of definition. Although it would be
+ > >>>interesting how you imagine a more logical alternative.
+ > >>
+ > >>The definition is: the object is only 'defined', if it's
+ > >>constructor has run completely. Something along those
+ > >>lines is used by C++.

The way constructos/destructors and inherited parts in C++ are complete
different then in object pascal. AFAIK the parent constructor/destructor
is called implicitly

OK, after some talks to the "real" C++ programmers overhere it is clear
that one can do the same in C++ as we do in Delphi, so there is no real
difference.

+ > >>After each constructor run, and only then, are the overriden
+ > >>function pointers written to the VMT. Personally, I think
+ > >>this is more logical, although maybe it's a matter of personal
taste.

Ow ? AFAIK the vmt pointers are filled in before the constructor is
called.

+ > >
+ > >
+ > > I can show you code where in the constructor a virtual
+ > > method is called
+ >
+ > Yes, show me the code :-).
+
+ Basically, it says the following:
+
+ Constructor TAppClientDataset.Create(AOwner : TComponent)
+
+ begin
+   Inherited;
+   // ... Various statements
+   InitDataEvents;
+ end;
+
+ The data events that must be initialized depend on the descendent.

You can also look at the various debugger classes. I've used it at several
places, for instance to get the ClassType of the breakpoints in the
Debugger.

+ Now, we could put this call in 'Loaded', but then they are not
+ initialized when we do for instance:
+
+ With TMySomeClientDataset.Create(Self) do
+   Try
+     // Do stuff.
+   Finally
+     Free;
+   end;
+
+ This kind of code is quite common.

Not only then, AFAIK loaded is only called if an object is loaded from
stream. If you create for instance a TButton, if I recall it correctly, no
call to Loaded is made.

+ Alternatively, we could put the code from InitDataEvents in the
+ constructor, and add additional initialization in the descendent
+ constructors. But sometimes, the events must be re-initialized:
+ That would mean duplicating the code from the constructor to
+ a separate call.
+
+ For these reasons, the 'InitDataEvents' is called in the
+ constructor and is virtual.
+
+ >
+ > > which does some additional initialization. The method needs to be
+ >
+ > What kind of initialization should I be thinking about?
+
+ Anything. Data events, extra variables.

Or in my case retrieving classes etc.

+ > > virtual since the initialization is different depending on the
+ > > descendent. That would not work in your scheme as it would
+ > > be invalid code...
+ >
+ > That's the only way?
+
+ It's never the _only_ way, but definitely the most convenient in many
+ cases.

Yup.

Marc






More information about the Lazarus mailing list