BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

OnDestroy and deleting objects
Goto page 1, 2  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Usage)
View previous topic :: View next topic  
Author Message
David Ayre
Guest





PostPosted: Mon Feb 20, 2006 4:03 pm    Post subject: OnDestroy and deleting objects Reply with quote



Hi,

I have a form, which OnShow, loads data into a number of
TMemoryStreams. These remain as long as the form is open.
When the form is closed, I delete the Memory streams. Where is
the best place to do this to take into account all eventualities?
Pointers to the MemoryStreams are declared in the header file,
and I use new TMemorySteam in the OnShow event handler.
I am using BDS 2006.

Thanks,

David Ayre
Back to top
David Ayre
Guest





PostPosted: Mon Feb 20, 2006 5:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote



Quote:


1) When the form is created at design time:

OnShow() can be 'dangerous' because it can be triggered *multiple*
times for the time when the form is active!


The form is available and I create a new modal form and delete
it each time I need it.


Quote:
If you use OnShow() then prevent from executing the same code
multiple times:

void __fastcall TForm1::FormShow(TObject *Sender)
{
bool HasPassedOnceOnShow = false;

if ( !HasPassedOnceOnShow )
{
HasPassedOnceOnShow = true;
MS = new TMemoryStream();
}
}


__fastcall TForm1::~TForm1()
{
delete MS;
}


I tried to do this but got an error. It said I had to use a
virtual destructor for VCL components and I wasn't sure how
to do this.

Cheers,

David
Back to top
Danzer
Guest





PostPosted: Mon Feb 20, 2006 5:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote



David Ayre wrote:

Quote:
Hi,

I have a form, which OnShow, loads data into a number of
TMemoryStreams. These remain as long as the form is open.
When the form is closed, I delete the Memory streams. Where is
the best place to do this to take into account all eventualities?
Pointers to the MemoryStreams are declared in the header file,
and I use new TMemorySteam in the OnShow event handler.
I am using BDS 2006.


Create a destructor for your form and do your final cleanup there.

Danzer
Back to top
Vladimir Stefanovic
Guest





PostPosted: Mon Feb 20, 2006 5:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

Quote:
OnDestroy

Never use OnDestroy() in C++ Builder because that event
can be triggered after the C++ destructor which is illegal.

The same is for FormCreate(). Use constructor instead.


Quote:
I have a form, which OnShow, loads data into a number of
TMemoryStreams. These remain as long as the form is open.
When the form is closed, I delete the Memory streams.Where is
the best place to do this to take into account all eventualities?
Pointers to the MemoryStreams are declared in the header file,
and I use new TMemorySteam in the OnShow event handler.
I am using BDS 2006.

First you must say if you create (new) the form every time (dynamically)
or you just Show()/Close*( that form, when it is created once at app
startup.


1) When the form is created at design time:

OnShow() can be 'dangerous' because it can be triggered *multiple*
times for the time when the form is active!

If you use OnShow() then prevent from executing the same code
multiple times:

void __fastcall TForm1::FormShow(TObject *Sender)
{
bool HasPassedOnceOnShow = false;

if ( !HasPassedOnceOnShow )
{
HasPassedOnceOnShow = true;
MS = new TMemoryStream();
}
}

Finally you can delete the object in OnClose() or in OnCloseQuery()

// void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
delete MS;
}



2) When the form is creating every time before showing:

I prefere this way (with pure constructor and destructor):

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
MS = new TMemoryStream();
}

__fastcall TForm1::~TForm1()
{
delete MS;
}



--
Best Regards,
Vladimir Stefanovic
Back to top
Vladimir Stefanovic
Guest





PostPosted: Mon Feb 20, 2006 7:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

If the form is available and you create it with new
each time you need it to show, then use this:

--- CPP ---

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
MS = new TMemoryStream();
}
__fastcall TForm1::~TForm1()
{
delete MS;
}

--- H ---

// ...
private:
TMemoryStream *MS;

public: // ...
__fastcall ~TForm1();
// ...

I'm not sure about virtual destructors (please show the actual message)
but I suppose that it is something about:

this:
__fastcall ~TForm1();

to be replaced with this::
virtual __fastcall ~TForm1();




Best Regards,
Vladimir Stefanovic
Back to top
Dennis Jones
Guest





PostPosted: Mon Feb 20, 2006 8:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

"David Ayre" <davidcayre (AT) ntlworld (DOT) com> wrote in message
news:43f9e25c$1 (AT) newsgroups (DOT) borland.com...
Quote:

Hi,

I have a form, which OnShow, loads data into a number of
TMemoryStreams. These remain as long as the form is open.
When the form is closed, I delete the Memory streams. Where is
the best place to do this to take into account all eventualities?
Pointers to the MemoryStreams are declared in the header file,
and I use new TMemorySteam in the OnShow event handler.
I am using BDS 2006.


Use a smart pointer, such as std::auto_ptr, boost::scoped_ptr, or
boost:shared_ptr and you won't have to worry about OnDestroy (bad idea
anyway) or a destructor.

- Dennis
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Feb 21, 2006 10:03 am    Post subject: Re: OnDestroy and deleting objects Reply with quote

"David Ayre" <davidcayre (AT) ntlworld (DOT) com> wrote in message
news:43f9e25c$1 (AT) newsgroups (DOT) borland.com...

Quote:
I have a form, which OnShow, loads data into a number of
TMemoryStreams.

I would not recommend using the OnShow event for that. Use the constructor
instead.

Quote:
Where is the best place to do this to take into account all eventualities?

The destructor.


Gambit
Back to top
David Ayre
Guest





PostPosted: Tue Feb 21, 2006 11:03 am    Post subject: Re: OnDestroy and deleting objects Reply with quote

Quote:
Use a smart pointer, such as std::auto_ptr, boost::scoped_ptr, or
boost:shared_ptr and you won't have to worry about OnDestroy (bad idea
anyway) or a destructor.

- Dennis


Thanks Dennis,


I'll have to get to grips with smart pointers. I tend to stick to
things that I understand, but I'll have to see if I can move on.

Cheers,

David
Back to top
David Ayre
Guest





PostPosted: Tue Feb 21, 2006 11:03 am    Post subject: Re: OnDestroy and deleting objects Reply with quote

Thanks Vladimir,

That was very helpful.

Best regards,

David

"Vladimir Stefanovic" <antivari (AT) po (DOT) sbb.co.yu> wrote:
Quote:
If the form is available and you create it with new
each time you need it to show, then use this:

--- CPP ---

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
MS = new TMemoryStream();
}
__fastcall TForm1::~TForm1()
{
delete MS;
}

--- H ---

// ...
private:
TMemoryStream *MS;

public: // ...
__fastcall ~TForm1();
// ...

I'm not sure about virtual destructors (please show the actual message)
but I suppose that it is something about:

this:
__fastcall ~TForm1();

to be replaced with this::
virtual __fastcall ~TForm1();




Best Regards,
Vladimir Stefanovic


Back to top
David Erbas-White
Guest





PostPosted: Tue Feb 21, 2006 5:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

Remy Lebeau (TeamB) wrote:
Quote:
"David Ayre" <davidcayre (AT) ntlworld (DOT) com> wrote in message
news:43f9e25c$1 (AT) newsgroups (DOT) borland.com...


I have a form, which OnShow, loads data into a number of
TMemoryStreams.


I would not recommend using the OnShow event for that. Use the constructor
instead.



Except that you can sometimes get bitten by this. Up until recently, I
had a TMaskEdit that I was populating with a value from the registry in
the constructor. It turns out that the value would be overwritten by
the design time value when the form is 'shown'. The ONLY way around
this that I've found was to use a private member of the form as a
'loaded' flag, and to use the OnShow event to load the data (once) into
the form.

I don't know if other controls have this 'feature', and I don't know why
this was occurring (due to time constraints I gave up tracing the
problem, once I found the 'fix').

I should add that this was on BCB5 Pro, YMMV. But the major concern I
have is that of not knowing which versions/components this particular
problem occurs in.

I would suggest that any items that you 'create' within the constructor
are fair game for being populated there, but any controls that are
present in the form (and this may well include hidden members of the
form) should be populated in the OnShow event (using a one-time-only
method).

David Erbas-White

Quote:

Where is the best place to do this to take into account all eventualities?


The destructor.


Gambit

Back to top
David Erbas-White
Guest





PostPosted: Tue Feb 21, 2006 6:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

David Erbas-White wrote:

I should add that I use a private member of the form (and not a 'static'
member in the OnShow event), as that makes it 'clearer' in the code
that it has to be set to 'false' in the constructor, and then set 'true'
in the OnShow event (when the data is loaded). Barring this, it becomes
easy for that static variable (especially if it is IN the OnShow event)
to only be cleared THE FIRST TIME THE FORM IS CREATED. This may not be
a problem for some users, but there are often forms that are created
multiple times (either for multiple instances, or opened/closed as
needed). The static variable will only be set false for the first
creation of the form, the private form variable is available for each
creation/deletion.

David Erbas-White
Back to top
David Erbas-White
Guest





PostPosted: Tue Feb 21, 2006 8:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

Remy Lebeau (TeamB) wrote:
Quote:
"David Erbas-White" <derbas (AT) arachneering (DOT) com> wrote in message
news:43fb41a3 (AT) newsgroups (DOT) borland.com...


Except that you can sometimes get bitten by this. Up until recently,
I had a TMaskEdit that I was populating with a value from the registry
in the constructor. It turns out that the value would be overwritten
by the design time value when the form is 'shown'.


The TCustomForm constructor streams in the DFM *before* the user-defined
constructor is run. So your own value should always be overriding the
design-time value, not the other way around. That has always worked fine
for me.


I'm sorry, I have to disagree. I don't have the time to run a complete
trace to find out why this occurs, but (at least in BCB5 Pro) running in
the debugger with debug libraries enabled, I could DEFINITIVELY see the
value change during the OnShow event. I could single step through, and
immediately prior to the OnShow call, the value would be my assigned
value, and once shown, it was the default value. This only occurred
with the TMaskEdit (and I only had one of these in all of my program),
so I don't know how/why it was occurring. I did single step as far as I
could through the OnShow function, but as most of it was simply sending
windows messages, and it was dealing with every component on the form, I
didn't have the time/patience to pursue it completely through.

There may have been a relationship to the fact that this control
apparently retains the 'last' value, and there may have been a bug in
relation to the code that would update the 'last' value with the
'current' value during the 'show' process, but again, I didn't bother
tracing it through completely.

Why it occurs, I can't definitively tell you. I can tell you that it
DOES occur, and that it affected multiple machines and operating systems.

Bear in mind that the above (possible) explanation means that the
statement about the DFM streaming first is probably correct, but it
doesn't negate the fact that the design-time value was being displayed,
regardless of the run-time value placed in the control.

David Erbas-White
Back to top
David Erbas-White
Guest





PostPosted: Tue Feb 21, 2006 8:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

Remy Lebeau (TeamB) wrote:
Quote:

The ONLY way around this that I've found was to use a private member
of the form as a 'loaded' flag, and to use the OnShow event to load the
data (once) into the form.


A better solution would be to expose a public Init() method in the form and
then call it after you create the form but before showing it, ie:

TMyForm *frm = new TMyForm(this);
frm->Init(); // <-- here
frm->Show();



Why is this a better method? This makes no sense -- it means that
(across the board, for all forms) one would have to do this two-step
process in order to show a form (or doing it modally). If one
implemented this, they would eventually write a MyShow function in the
form that would do both steps, and then you've added TWO functions.
Further, the Init function still needs a method to ensure that this is
only done ONCE -- and you're back to having a variable that indicates
such has occurred.

Bear in mind that lots of things can cause one to have to re-Show a
form, and you don't want to initialize it more than once -- you only
want it done once per form creation.

This is a classic case (IMHO) of the existing functionality providing a
solution -- why would one NOT use the OnShow event here??? One can add
it to their 'generic' form use, and it is self contained WITHIN THE FORM
CLASS, so that no external calls have to be made (as you've done above).
That, after all, is supposed to be what OOP is all about...

David Erbas-White
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Feb 21, 2006 8:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

"David Erbas-White" <derbas (AT) arachneering (DOT) com> wrote in message
news:43fb41a3 (AT) newsgroups (DOT) borland.com...

Quote:
Except that you can sometimes get bitten by this. Up until recently,
I had a TMaskEdit that I was populating with a value from the registry
in the constructor. It turns out that the value would be overwritten
by the design time value when the form is 'shown'.

The TCustomForm constructor streams in the DFM *before* the user-defined
constructor is run. So your own value should always be overriding the
design-time value, not the other way around. That has always worked fine
for me.

Quote:
The ONLY way around this that I've found was to use a private member
of the form as a 'loaded' flag, and to use the OnShow event to load the
data (once) into the form.

A better solution would be to expose a public Init() method in the form and
then call it after you create the form but before showing it, ie:

TMyForm *frm = new TMyForm(this);
frm->Init(); // <-- here
frm->Show();

Quote:
I would suggest that any items that you 'create' within the constructor
are fair game for being populated there, but any controls that are present
in the form (and this may well include hidden members of the form) should
be populated in the OnShow event (using a one-time-only method).

I disagree with that. *All* design-time components are streamed by
TCustomForm's constructor before your own constructor begins running.


Gambit
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Feb 21, 2006 9:03 pm    Post subject: Re: OnDestroy and deleting objects Reply with quote

"David Erbas-White" <derbas (AT) arachneering (DOT) com> wrote in message
news:43fb67e2 (AT) newsgroups (DOT) borland.com...

Quote:
I'm sorry, I have to disagree. I don't have the time to run a complete
trace to find out why this occurs, but (at least in BCB5 Pro) running in
the debugger with debug libraries enabled, I could DEFINITIVELY
see the value change during the OnShow event.

Like I said earlier, it works fine for me. I cannot reproduce the issue in
BCB 5 (Ent). When I change the TMaskEdit::Text in the form's constructor,
the design-time value is overwritten as expected. Inside the form's OnShow
event handler, the TMaskEdit::Text propety is set to the value I assigned in
the form's constructor, as expected. Then, when the OnShow event handler
changes the TMaskEdit::Text property, that is the value that I see when the
form becomes visible onscreen, as expected.

Quote:
Why it occurs, I can't definitively tell you. I can tell you that it
DOES occur, and that it affected multiple machines and operating
systems.

Then you need to provide CONCRETE steps to reliably reproduce it. Because
right now, I cannot reproduce it at all.


Gambit
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Usage) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.