Board index » cppbuilder » Create VCL

Create VCL


2003-09-03 03:11:15 PM
cppbuilder102
How can I create a VCL object by code, without drag the component in the
form? I've tried to write:
TObject* myObject=new TObject;
but an error occour...
Thanks, Christian.
 
 

Re:Create VCL

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
Quote
Label1->Caption = TObject().ClassName();
You cannot create instanes of VCL objects on the stack, they must be on the
heap. They do not work correctly on the stack.
Gambit
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (www.grisoft.com).
Version: 6.0.515 / Virus Database: 313 - Release Date: 9/1/03
 

Re:Create VCL

"Thor Magne" < XXXX@XXXXX.COM >wrote in message
Quote

TEdit * dynedit= new TEdit(Form1);
dynedit->Show();

It works, the edit is created, but I can not see it on the form.
Where do I have to go from here?
You should assign its Parent property, e.g.;
TEdit* dynedit = new TEdit(Form1);
dynedit->Parent = Form1;
Have a look at the Parent property in the help.
Ralph
 

{smallsort}

Re:Create VCL

"Chri" < XXXX@XXXXX.COM >wrote in message
Quote
How can I create a VCL object by code, without drag the component in the
form? I've tried to write:
TObject* myObject=new TObject;
but an error occour...
Could you please specify what kind of error you are receiving?
Ralph
 

Re:Create VCL

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
Quote
Example 2 : Or using unamed objects

Label1->Caption = TObject().ClassName();
You probably meant;
Label1->Caption = TObject::ClassName();
But, how is this creating objects? ;)
Ralph
 

Re:Create VCL

Hi Ralph,
No, I meant what I wrote. This is a mechanism that I discovered while
working with constructors. When an object is created the
corresponding constructor is automatically called, then I thought
would the reverse process occur? If I call or invoke a method of a
given class via the constructor of that class
class X
{
public:
Type method();
};
X().method();
would an object of that class be created? I found that the answer
was yes, and not without a surprise.
Since then, I made some designs based on this undocumented C++ feature.
You can find an example in my WEB pages:
www.geocities.com/rodolfofrino/UnnamedObjects.html
www.geocities.com/rodolfofrino/CyclicToolbar.html
No-one told us about this feature, not even Stroutroup, I think this is one
of those
misterious and obscure things that the creator if C++ did not want to
reveal.
But "Time" always tell (or almost always, should I say {:-)
Rodolfo
"Ralph Kazemier" < XXXX@XXXXX.COM >wrote in message
Quote

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...
>Example 2 : Or using unamed objects
>
>Label1->Caption = TObject().ClassName();

You probably meant;

Label1->Caption = TObject::ClassName();


But, how is this creating objects? ;)


Ralph


 

Re:Create VCL

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
Quote
No-one told us about this feature, not even Stroutroup, I think this is one
of those
misterious and obscure things that the creator if C++ did not want to
reveal.
It is not a feature. There is simply a temporary object created. But as Remy
already pointed out, VCL classes must be created on the heap. So in that case
your code must look like;
Label1->Caption = new TObject()->ClassName();
Which obviously will leak. That's why I thought you meant to call (static)
ClassName().
Ralph
 

Re:Create VCL

Quote
It is not a feature. There is simply a temporary object created.
The feature is the way in which we can invoke a method, without
creating an explicit instance of the class. The ability to create an object
(unnamed or temporary) by calling
X().method();
is a feature. Of course temporary objects are created in other circumstances
as well, such as in the case of a function returning an object.
Quote
VCL classes must be created on the heap. So in that case
your code must look like;
That is not always true. There are special cases in which you
can create VCL objects on the stack (like in the example I posted earlier)
then you can invoke a method of this object and this method will produce
a correct result.
Rodolfo
 

Re:Create VCL

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
Quote
>VCL classes must be created on the heap. So in that case
>your code must look like;

That is not always true. There are special cases in which you
can create VCL objects on the stack (like in the example I posted earlier)
then you can invoke a method of this object and this method will produce
a correct result.
Whether you can instantiate TObject-descendants on the stack does not change the
fact that they do not work correctly on the stack. Your example probably shows
a bug in the BC++B compiler. I have verified that the destructor of TObject is
_not_ called. Please take the effort to test the following example and you will
see what I mean.
class TmyObject: public TObject {
public:
__fastcall TmyObject(): FData(new int[1024]) {
}
virtual __fastcall ~TmyObject() {
delete FData;
}
};
ShowMessage( TmyObject().ClassName() );
Ralph
 

Re:Create VCL

Quote
>That is not always true. There are special cases in which you
>can create VCL objects on the stack (like in the example I posted
earlier)
>then you can invoke a method of this object and this method will produce
>a correct result.

Whether you can instantiate TObject-descendants on the stack does not
change the
fact that they do not work correctly on the stack.
I said that the results of some methods are correct, I did NOT say that the
destructor
of a VCL object created on the stack will work.
Rodolfo
 

Re:Create VCL

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
Quote
I said that the results of some methods are correct, I did NOT say that the
destructor of a VCL object created on the stack will work.
Granted. But then, why would you want to use a piece of code that leaks?
TObject-descendants are simply not allowed to be instantiated on the stack,
period. Normally the compiler won't let you do that. You have found a bug in
the compiler. My advice, do not make features out of bugs. They may change
over time and as a result you can't use the code anymore.
Ralph
 

Re:Create VCL

When you work with descendants of TObject on the stack
you don't have heap memory to free, therefore you cannot
call "delete pObject". You have to use a totally different technique.
For example you can initialize your data with the one-argument
constructor and you can call your destructor directly via the
default constructor as I did in this example.
class TmyObject: public TObject
{
int* p;
public:
__fastcall TmyObject(int size): TObject()
{
ShowMessage("One-argument Contructor");
p = new int[size];
}
__fastcall TmyObject(): TObject()
{
ShowMessage("Default Contructor");
}
virtual __fastcall ~TmyObject()
{
ShowMessage("Destructor");
delete []p;
}
};
//--------------------------------------------------------------------------
-
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Create a TmyObject on the stack
ShowMessage(TmyObject(1024).ClassName());
TmyObject().~TmyObject(); // Invoke destructor directly
}
//--------------------------------------------------------------------------
-
void __fastcall TForm1::Button2Click(TObject *Sender)
{
// Create a TmyObject on the Heap
TmyObject* O = new TmyObject();
ShowMessage(O->ClassName());
// Delete memory allocated by new
// and invoke destructor
delete O;
}
I give this as an counter-example, however I am not saying that we should
create decesntants of VCL TObject on the stack. The Heap is where we
should be doind this things. Just keep in mind that some things can be done
on the stack, and they will work in some cases provided that you use
the appropriate methods which in general will be different to those use
when we create on the Heap.
Rodolfo
"Ralph Kazemier" < XXXX@XXXXX.COM >wrote in message
Quote

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>>VCL classes must be created on the heap. So in that case
>>your code must look like;
>
>That is not always true. There are special cases in which you
>can create VCL objects on the stack (like in the example I posted
earlier)
>then you can invoke a method of this object and this method will produce
>a correct result.

Whether you can instantiate TObject-descendants on the stack does not
change the
fact that they do not work correctly on the stack. Your example probably
shows
a bug in the BC++B compiler. I have verified that the destructor of
TObject is
_not_ called. Please take the effort to test the following example and
you will
see what I mean.


class TmyObject: public TObject {

public:
__fastcall TmyObject(): FData(new int[1024]) {
}

virtual __fastcall ~TmyObject() {
delete FData;
}
};

ShowMessage( TmyObject().ClassName() );


Ralph




 

Re:Create VCL

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
Quote
ShowMessage(TmyObject(1024).ClassName());
TmyObject().~TmyObject(); // Invoke destructor directly
The code creates two seperates instances on the stack. The destructor will be
called for the second instance, since its destructor is called explicitly. Note
that it will still result in a memory leak for the first instance. It can only
work if the method invoked, deletes the instance.
Quote
I give this as an counter-example, however I am not saying that we should
create decesntants of VCL TObject on the stack.
Then why did you show the (first) example in the first place? ;)
Ralph
 

Re:Create VCL

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
Quote
Yes, you can. I just did it and it worked!
I have also done it before... BUT, if you look closer at it, the destructor
will not be called correctly when the object goes out of scope. I have
already confirmed and reported the issue to QC awhile ago. TObject classes
are not meant to be used on the stack - period! It is a *requirement* for
the Delphi Pascal side of the VCL. The VCL is written in Delphi Pascal, it
does not support objects on the stack. The only reason it *appears* to work
under C++ is because C++ does allow objects on the stack in general. As
such, you enter into an incompatibility between the rules of Delphi and the
rules of C++, and you end up with undefined behavior as a result of the
conflicting natures of the languages being used for the same object.
Quote
Don't believe 100% of what Borland tells you, there are
exceptions.
Borland didn't say anything about it. I do, because I already experimented
with it awhile ago and have come to my own conclusions on my own.
Gambit
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (www.grisoft.com).
Version: 6.0.515 / Virus Database: 313 - Release Date: 9/1/03
 

Re:Create VCL

"Rodolfo Frino" < XXXX@XXXXX.COM >wrote in message
Quote
I doubt that this is a bug
It is a bug. VCL objects cannot be used on the stack. The compiler should
not have allowed it to begin with.
Quote
I will try it on VC++ to confirm it.
That is not a fair comparison. VC++ does not use the VCL, it plays by a
completely different set of rules for its own frameworks. The behavior you
are trying to exploit is well-known and works fine in general *as long as*
you are not using TObject-derived objects. As soon as you introduce TObject
into the mix, you can no longer use that feature of the language for that
class.
Quote
In the meantime please have a look at my other post in which
I show you that there are ways of preventing leaks when
you create VCL objects in the Heap, at lesst in the example
I posted :-)
You're missing the whole point.
Gambit
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (www.grisoft.com).
Version: 6.0.515 / Virus Database: 313 - Release Date: 9/1/03