Board index » delphi » Object Pascal Assignments and Classes

Object Pascal Assignments and Classes

Ok, this might be an easy one for somebody out there.  Here's the deal.
I have created a class, let's say TClass, and I instantiate it in
procedure A as Var1.  I then pass Var1 to procedure B, and assign it to
Var2, again of type TClass.  

For example, pls refer to the following code block.  When we free Var1
in procedure A, our application crashes when we terminate it.  When we
don't free Var1, no exceptions arise.  In procedure B, where we pass
Var1 and assign it to Var2, we can access all member variables that were
in Var1 via Var2.

*The question is*:  Does the assignment in object pascal force Var2 to
point to Var1, or does it make a COPY of Var1 and reference it via Var2?
It seems like since when we free Var1, causing an exception violation,
Pascal is not making a copy, but setting Var1 to point to Var2.  So,
when we free Var1, Var2 has nothing to point to?

class TClass...
..

procedure A
var
        Var1:  TClass;
begin
        Var1.Create;
        B( Var1 );

        Var1.Free;      // This causes an exception on app close.
end;

..
..
..

procedure B ( Var1 )
var
        Var2:  TClass;
begin
        Var2.Create;

        Var2 := Var1;   // Var2 points to Var1?
                        // Or is Var2 a copy of Var1?
end;

Any comments would be greatly appreciated.

- Jon

 

Re:Object Pascal Assignments and Classes


In article <326E90B2.5...@carecentric.com>,
   Jon Czernel <jon...@carecentric.com> wrote:

Quote
>Ok, this might be an easy one for somebody out there.  Here's the deal.
>I have created a class, let's say TClass, and I instantiate it in
>procedure A as Var1.  I then pass Var1 to procedure B, and assign it to
>Var2, again of type TClass.  

>For example, pls refer to the following code block.  When we free Var1
>in procedure A, our application crashes when we terminate it.  When we
>don't free Var1, no exceptions arise.  In procedure B, where we pass
>Var1 and assign it to Var2, we can access all member variables that were
>in Var1 via Var2.

>*The question is*:  Does the assignment in object pascal force Var2 to
>point to Var1, or does it make a COPY of Var1 and reference it via Var2?
>It seems like since when we free Var1, causing an exception violation,
>Pascal is not making a copy, but setting Var1 to point to Var2.  So,
>when we free Var1, Var2 has nothing to point to?

>class TClass...

Delphi will let you get away with that due to name-scoping rules, but
you should name it TMyClass; TClass is defined as class of TObject.
(A class reference)

Quote
>procedure A
>var
>    Var1:  TClass;
>begin
>    Var1.Create;

If the constructor is static, this is okay.  For classes with virtual
constructors (e.g. components), be sure to use the Var1 := TMyClass.Create
syntax.

Quote
>    B( Var1 );

>    Var1.Free;      // This causes an exception on app close.
>end;

>procedure B ( Var1 )
>var
>    Var2:  TClass;
>begin
>    Var2.Create;

>    Var2 := Var1;   // Var2 points to Var1?
>                    // Or is Var2 a copy of Var1?

This assignment here is a "shallow copy"; yes, it makes Var2 point to
Var1, and there are no reference-counting semantics.  The convention
for a "deep copy" (the equivalent of a copy constructor in C++) is to
create an Assign method.

The Assign method is defined further down the tree in TPersistent, but
that needn't stop you from making your own if you want a small, tight
class.  I believe (but don't know for sure) that the default behavior of
Assign in TPeristent-based classes is to copy published properties from
the source to the destination.

A simple definition for your own might be along the lines of:

procedure TMyClass.Assign(MySource: TMyClass);
begin
  Member1 := MySource.Member1;
end;

(It may seem inelegant, but this is the stuff copy constructors are made
of)

Then... Var2.Assign(Var1);

Quote
>end;

>Any comments would be greatly appreciated.

Hope that helps out a bit.

Re:Object Pascal Assignments and Classes


Quote
Malibu Software wrote:

> In article <326E90B2.5...@carecentric.com>,
>    Jon Czernel <jon...@carecentric.com> wrote:

> >procedure A
> >var
> >       Var1:  TClass;
> >begin
> >       Var1.Create;

> If the constructor is static, this is okay.  

Really? How come? Var1 is just a pointer. Even though the call will work,
you'll be working with a non-sensical self pointer. The (later) Var1.Free
will then attempt to free a non-existing object, and you'll get a GPF,
Invalid Pointer Operation or some other fun exception at some later point.

Bottom line:
Always use:
  Var1 := TMyObject.Create;

Always!

M.

--
Ettertraktet kaffe, er det ekstra god kaffe?

mailto:martin.lars...@delfi-data.msmail.telemax.no
http://www.delfidata.no/users/~martin

Re:Object Pascal Assignments and Classes


Hm, have you tried to read Object Pascal language manuals?

In article <326E90B2.5...@carecentric.com>, Jon Czernel says...

Quote
> Ok, this might be an easy one for somebody out there.  Here's the deal.
[snip]

> *The question is*:  Does the assignment in object pascal force Var2 to
> point to Var1, or does it make a COPY of Var1 and reference it via Var2?
> It seems like since when we free Var1, causing an exception violation,
> Pascal is not making a copy, but setting Var1 to point to Var2.  So,
> when we free Var1, Var2 has nothing to point to?

> class TClass...

To avoid stupid mistakes, try not to use TClass as a name for your
class, it is already defined as

type TClass = Class of TObject;

Quote
> ..

> procedure A
> var
>    Var1:  TClass;
> begin
>    Var1.Create;            

^^ you call it assignment!? Valid allocation looks like:

Var1 := TClass.Create;

Quote
>    B( Var1 );

>    Var1.Free;      // This causes an exception on app close.
> end;

> ..
> ..
> ..

> procedure B ( Var1 )
> var
>    Var2:  TClass;
> begin
>    Var2.Create;

same error.

Quote

>    Var2 := Var1;   // Var2 points to Var1?

contents of Var2 lost. now Var2 points to passed object. It doesn't
matter, becouse in your code both - Var1 and Var2 - contain some trash
from the stack.
Quote
>                    // Or is Var2 a copy of Var1?
> end;

> Any comments would be greatly appreciated.

> - Jon

Re:Object Pascal Assignments and Classes


Quote
Malibu Software wrote:

> clip..
> >                       // Or is Var2 a copy of Var1?

> This assignment here is a "shallow copy"; yes, it makes Var2 point to
> Var1, and there are no reference-counting semantics.  The convention
> for a "deep copy" (the equivalent of a copy constructor in C++) is to
> create an Assign method.

> The Assign method is defined further down the tree in TPersistent, but
> that needn't stop you from making your own if you want a small, tight
> class.  I believe (but don't know for sure) that the default behavior of
> Assign in TPeristent-based classes is to copy published properties from
> the source to the destination.

> A simple definition for your own might be along the lines of:

> procedure TMyClass.Assign(MySource: TMyClass);
> begin
>   Member1 := MySource.Member1;
> end;

> (It may seem inelegant, but this is the stuff copy constructors are made
> of)

> Then... Var2.Assign(Var1);

> >end;

> >Any comments would be greatly appreciated.

> Hope that helps out a bit.

Yes, thanks for ignoring for the most part my sloppy syntax to get down
to the bottom-line question that you *did* shed some light upon.  

Thanks!

---------------------------------------------------
Jon Czernel                  jon...@carecentric.com

Re:Object Pascal Assignments and Classes


Quote
Glen Y wrote:

> Hm, have you tried to read Object Pascal language manuals?

Yes, I have.

Quote

> In article <326E90B2.5...@carecentric.com>, Jon Czernel says...
> > Ok, this might be an easy one for somebody out there.  Here's the deal.
> [snip]

> > *The question is*:  Does the assignment in object pascal force Var2 to
> > point to Var1, or does it make a COPY of Var1 and reference it via Var2?
> > It seems like since when we free Var1, causing an exception violation,
> > Pascal is not making a copy, but setting Var1 to point to Var2.  So,
> > when we free Var1, Var2 has nothing to point to?

> > class TClass...

> To avoid stupid mistakes, try not to use TClass as a name for your
> class, it is already defined as

Yes, Yes, I know...I typed this in a hurry to get the question out, I
wasn't too worried about naming conventions, etc., just wanted to get
quickly to the bottom line question.

Quote

> type TClass = Class of TObject;

> > ..

> > procedure A
> > var
> >       Var1:  TClass;
> > begin
> >       Var1.Create;

> ^^ you call it assignment!? Valid allocation looks like:

Yes, as I said before, I typed this in a hurry, I understand.

- Show quoted text -

Quote

> Var1 := TClass.Create;

> >       B( Var1 );

> >       Var1.Free;      // This causes an exception on app close.
> > end;

> > ..
> > ..
> > ..

> > procedure B ( Var1 )
> > var
> >       Var2:  TClass;
> > begin
> >       Var2.Create;

> same error.

> >       Var2 := Var1;   // Var2 points to Var1?

> contents of Var2 lost. now Var2 points to passed object. It doesn't
> matter, becouse in your code both - Var1 and Var2 - contain some trash
> from the stack.

Ok, after all that not a real answer to the basic question, thanks.

- Show quoted text -

Quote
> >                       // Or is Var2 a copy of Var1?
> > end;

> > Any comments would be greatly appreciated.

> > - Jon

Re:Object Pascal Assignments and Classes


Quote
Jon Czernel wrote:

> Ok, this might be an easy one for somebody out there.  Here's the deal.
> I have created a class, let's say TClass, and I instantiate it in
> procedure A as Var1.  I then pass Var1 to procedure B, and assign it to
> Var2, again of type TClass.

> For example, pls refer to the following code block.  When we free Var1
> in procedure A, our application crashes when we terminate it.  When we
> don't free Var1, no exceptions arise.  In procedure B, where we pass
> Var1 and assign it to Var2, we can access all member variables that were
> in Var1 via Var2.

> *The question is*:  Does the assignment in object pascal force Var2 to
> point to Var1, or does it make a COPY of Var1 and reference it via Var2?
> It seems like since when we free Var1, causing an exception violation,
> Pascal is not making a copy, but setting Var1 to point to Var2.  So,
> when we free Var1, Var2 has nothing to point to?

        An assignment copies the value of one variable to the other.
This means if you assign a value to a pointer variable then exactly four
bytes get copied, because a pointer is a variable containing four bytes.
Objects in Delphi are just pointers.

Quote
> class TClass...

        If you want help with the syntax you _really_ have to give the example
more carefully. The line above is already wrong, you meant

type TClass...

If none of the code makes any sense then it's impossible to tell what the
real problem is - the real problem is hidden in all the "oh, that's not
what I meant" stuff.

Quote
> procedure A
> var
>         Var1:  TClass;
> begin
>         Var1.Create;

        There's jillions of examples of object creation in the docs, and
not one of them looks like this, every single one looks like

Var1:= TClass.Create;

(this is in re your reply to the guy who asked if you'd read any of the
manuals.)

Quote
>         B( Var1 );

>         Var1.Free;      // This causes an exception on app close.

        Of course it does, you're referencing an uncreated object.

Quote
> end;

> ..
> ..
> ..

> procedure B ( Var1 )
> var
>         Var2:  TClass;
> begin
>         Var2.Create;

>         Var2 := Var1;   // Var2 points to Var1?
>                         // Or is Var2 a copy of Var1?
> end;

        Var2 is a pointer - IF Var1 pointed to a valid object then Var2 would
now point to the same object.

--
David Ullrich

?his ?s ?avid ?llrich's ?ig ?ile
(Someone undeleted it for me...)

Re:Object Pascal Assignments and Classes


In article <326F3BDB.1...@delfi-data.msmail.telemax.no>,
   Martin Larsson <martin.lars...@delfi-data.msmail.telemax.no> wrote:

Quote
>Malibu Software wrote:

>> In article <326E90B2.5...@carecentric.com>,
>>    Jon Czernel <jon...@carecentric.com> wrote:

>> >procedure A
>> >var
>> >       Var1:  TClass;
>> >begin
>> >       Var1.Create;

>> If the constructor is static, this is okay.  

>Really? How come? Var1 is just a pointer. Even though the call will work,
>you'll be working with a non-sensical self pointer. The (later) Var1.Free
>will then attempt to free a non-existing object, and you'll get a GPF,
>Invalid Pointer Operation or some other fun exception at some later
point.

>Bottom line:
>Always use:
>  Var1 := TMyObject.Create;

Indeed, you're right on that - I'd been under the impression that the
:= TMyClass.Create syntax was necessary because of virtual constructors,
which would need to point to a valid VMT, but I guess that the static
Creates don't actually modify the pointer itself (as old TP7 New would).

Had to try it, of course.  It tried and failed.  It tried... and died :)

Other Threads