Jump to content
bravesofts

Class Instance vs Object Instance

Recommended Posts

Posted (edited)

First : i have this code:

type
  TClass_Instance = class(TClass_Ancestor)

  end;

what happen at runtime when our program is using this Unit?

i mean exactly this Explicit

TClass_Instance = class(TClass_Ancestor)

does this Allocate something in Memory ? or system resources ....

second:

ihave this declaration here:

var
  vObj_Instance: TClass_Instance;
begin

end;

what happen at runtime when we are declaring some Objects ?

i mean exactly this Declaration 

vObj_Instance: TClass_Instance;

does this Allocate something in Memory ? or system resources ....

third:

  i have this code here:

type
  {$M+}
  TBaseForm = class(TForm) // This my template Base Form
    procedure Abstracted_Event(Sender: TObject); virtual; abstract;
  end;

  TSubBase_1 = class(TBaseForm)
    // SubBase_1 Members goes here ..
  published
    procedure Abstracted_Event(Sender: TObject); Override;  
  end;

  TSubBase_2 = class(TBaseForm)
  // SubBase_2 Members goes here ..
  published
    procedure Abstracted_Event(Sender: TObject); Override;
  end;

  TSubBase_3 = class(TBaseForm)
  // SubBase_3 Members goes here ..
  published
    procedure Abstracted_Event(Sender: TObject); Override;
  end;

i have this super procedure for calling sub forms acording to their Class Names:

procedure Get_SubForm(AFormClass: TFormClass; aOwner: TComponent; aParent: TWinControl);
var
  vObjInstance: TBaseForm; // Define Object Instance Type;
  vRef: TBaseForm; // our Object vRef is the Universal variable for All SubForms that inherited from TBaseForm
begin
  vObjInstance := TBaseForm(AFormClass.NewInstance); //Fill Object [vObjInstance] with [AFormClass.NewInstance] ..
  vRef         := vObjInstance.Create(aOwner); //Fill Object [vRef] with [vObjInstance.Create] ..
  try
    vRef.Parent      := aParent;
    vRef.Align       := alClient;
    vRef.BorderStyle := bsNone;
    vRef.OnShow      := vRef.Abstracted_Event;
  finally
    vRef.Show;
  end;
end;
Quote

  this code could be inside the baseform as global method or inside our MainForm Application

my question is :

what happen here:

 vObjInstance := TBaseForm(AFormClass.NewInstance); //Fill Object [vObjInstance] with [AFormClass.NewInstance] ..

at runtime ...?

does this line Above is trying to replace the first declaration Above here:

var
  vObjInstance: TBaseForm; // Define Object Instance Type;

in other words:

does NewInstance Above is trying to redeclare our variable vObjInstance with Another Type ?

if not (so what happen exactlly ?)

Another sample Example:

procedure TFrmMain.Btn_CreateObjClick(Sender: TObject);
var
  vObj_Instance: TButton;  // declaration Type of our Object
  vRef: TButton;
begin
  vObj_Instance := TButton(TButton.NewInstance);

  vRef          := vObj_Instance.Create(Self);
  try
    vRef.Parent := Self;
    vRef.Name   := 'Btn_vObj'+ ComponentCount.ToString;
    vRef.SetBounds(Round(8 * fScaleFactor), Round(48 * fScaleFactor), Round(185 * fScaleFactor), Round(41 * fScaleFactor));

  finally
    vRef.Visible := True;
  end;
end;

here i'm using the same approach Above that using TBaseForm but with one base Class TButton

my question is:

we used to use this Rule here:

<vObject> := <ClassName>.<ConstructorName> ;

but here we have an object trying to Allocate the memory (fiil the Class inside that variable) for Another Object ...

my Remark:

procedure TFrmMain.Btn_CreateObjClick(Sender: TObject);
var
//  vObj_Instance: TButton; 
  vRef: TButton;
begin
//  vObj_Instance := TButton(TButton.NewInstance);

  vRef          := Btn_CreateObj.Create(Self);
  try
    vRef.Parent := Self;
    vRef.Name   := 'Btn_vObj'+ ComponentCount.ToString;
    vRef.SetBounds(Round(8 * fScaleFactor), Round(48 * fScaleFactor), Round(185 * fScaleFactor), Round(41 * fScaleFactor));

  finally
    vRef.Visible := True;
  end;
end;

if we click on button Btn_CreateObj  the object will be created but the Button Btn_CreateObj will be disappear !!! and when closing the app will have a memory leaks !!!

my Approach of using another variable as a mediator, remind me with A & B replacement values

var
  A, B, C: integer;
begin
  A := 10; B := 5;

 // Solving requiring us Another Variable with the same Type
  C := A;
  A := B; 
  B := C; // AND IT'S DONE ..
   
end;

finally:

  what is a Class Instance and an Object Instance?

  and is my Approach for creating base forms is a good approach or not ?

thanks in Advance...

Edited by bravesofts

Share this post


Link to post

A class declaration doesn't allocate any memory unless there are class variables inside that class.

Memory is allocated when - at run time - the constructor is called.

A variable having a type equal to a class is actually a pointer to the memory allocated for the class instance by calling the constructor. Class are handled "by reference".

 

By the way, you should by a good book about Delphi programming (the language, not the runtime libraries). Look there to make your choice: https://delphi-books.com/en/

 

  • Like 2

Share this post


Link to post
26 minutes ago, FPiette said:

A variable having a type equal to a class is actually a pointer to the memory allocated for the class instance by calling the constructor. Class are handled "by reference".

 

and what about the exe it's self ?

does A variable having a type equal to a class is actually a pointer to the memory allocated for the class instance inside the exe it's self and not comming from calling the constructor. !!!

i mean the delphi is deployed for us a ready to use objects variables that pointer to the exe it's self (pre Allocated Classes)

Share this post


Link to post

What FPiette said above ^^^^^^^^^^^^^ is accurate, if not a bit brief.

 

What you're thinking is how RECORD types work. They act like STRUCTs in C/C++.

 

In the last version of Turbo Pascal, an 'object' type was introduced that was like a class (with both data and method members) that behaved like a record (static memory allocation).

 

When Delphi was introduced, it deprecated 'object' types and added a 'class' type where everything was implicitly derived from a base class called TObject, and variables declared as type 'class' are references (pointers) to dynamic objects on the heap. 

 

Unlike regular Pascal pointers that need to be dereferenced with the '^' operator, references to class instances are implicitly dereferenced and allow you to just use the '.' operator to access members.

 

That's one reason why you can see the same code expressed in Delphi and C++ and the C++ code looks horrendously more complicated. (The C++ is closer to what you'd see in Delphi using records or deprecated 'object' types.)

 

There's a free book that Marco published via EMBT that is a great introduction to Delphi. It'll take you step-by-step through all of this stuff.

 

BTW, RECORD types in Delphi have evolved to the point where they're very similar to classes today, but they still retain their static memory aspect when you declare instances of them.

 

Record instances are 'value-based' whereas class instances are 'reference-based'.

  • Like 1

Share this post


Link to post
4 minutes ago, bravesofts said:

and what about the exe it's self ?

does A variable having a type equal to a class is actually a pointer to the memory allocated for the class instance inside the exe it's self and not comming from calling the constructor. !!!

i mean the delphi is deployed for us a ready to use objects variables that pointer to the exe it's self (pre Allocated Classes)

What languages are you most familiar with? You seem to have certain ways you're thinking that are not applicable to Delphi, so it would be helpful to know where you're coming from.

  • Like 1

Share this post


Link to post

If you have a Delphi license, you can get the latest version of Marco's book from the portal. Maybe it's available elsewhere for free as well.

 

you can also get it from Amazon Kindle here:

 

https://amzn.to/3iuvbTf

 

  • Like 1

Share this post


Link to post
Quote

What languages are you most familiar with? You seem to have certain ways you're thinking that are not applicable to Delphi, so it would be helpful to know where you're coming from.

honestly i'm a native Delphi !!!

-------

my post here is to understand exactly what delphi  is that i was used before without a deep attention to delphi details

Share this post


Link to post
Posted (edited)
17 minutes ago, bravesofts said:

honestly i'm a native Delphi !!!

-------

my post here is to understand exactly what delphi  is that i was used before without a deep attention to delphi details

well, you seem more familiar with what Pascal offered, before Dephi introduced 'class' types.

 

And I don't know what to say about the question regarding EXEs. That's totally unrelated to storage allocation of classes. Or I'm not understanding your question.

 

See if you can snag a copy of Marco's book (ask Google) and work your way through it. That will get you onto very solid ground.

Edited by David Schwartz
  • Like 1

Share this post


Link to post
1 hour ago, bravesofts said:

 


 vObjInstance := TBaseForm(AFormClass.NewInstance); //Fill Object [vObjInstance] with [AFormClass.NewInstance] ..

 

Don't ever call NewInstance - this s internal method. https://docwiki.embarcadero.com/Libraries/Sydney/en/System.TObject.NewInstance

 

You should call constructor to create (allocate) new object.

 

 vRef := TBaseForm(AFormClass.Create(aOwner));

 

or you can typecast with as operator which will fail at runtime if the AFormClass is not TBaseForm

 

 vRef := AFormClass.Create(aOwner) as TBaseForm;

 

When you declare variable

 

var
  vRef: TBaseForm;

 

This will only automatically allocate pointer (reference) to your future form - if this is local variable it will be allocated on the stack, if it is field it will be allocated as part of object instance. This is automatic and you don't need to manage memory for that pointer, variable itself. Only when you call constructor actual object instance will be created and allocated - if you create form with owner, that owner will be responsible for releasing its memory. If you pass nil for owner, you need to release it yourself.

 

There is no class instance here, only object instances. Class instance is constructed when you declare class variables in class declaration - and they are automatically allocated and deallocated and there is only single one per class. Again you are not using them in your code.

Following is example of class variable declaration. Variable Foo is accessible as TBaseForm.Foo or as vRef.Foo but it will be the same shared integer variable.

TBaseForm = class(TForm)
public
  class var Foo: Integer;
end;

 

  • Like 1

Share this post


Link to post
Posted (edited)
1 hour ago, bravesofts said:

and what about the exe it's self ?

does A variable having a type equal to a class is actually a pointer to the memory allocated for the class instance inside the exe it's self and not comming from calling the constructor. !!!

As I said, a variable having a type equal to a class use NO MEMORY until it is assigned a value coming from the constructor (A constructor use dynamic memory allocation to create space for the object instance and return the pointer). If you copy another variable value, then you have a second pointer pointing to the same object instance. beware of pointer becoming invalid as soon as the object pointed to is destroyed.

Edited by FPiette
  • Like 1

Share this post


Link to post
Posted (edited)

what happen at runtime when we are declaring some Objects ?

i mean exactly this Declaration 

vObj_Instance: TClass_Type; 

does this Allocate something in Memory ? or system resources ....

 

No it does not I think you want a reference.

Here is example where several forms have created and they may have Comboboxes in them.

We use screen to find the forms and component list to find a combobox for the

demo.  

 

procedure TEventBoss.showComboBoxDropDowns;
var
  I,C: integer;
  F: TForm;     
  //Ctrl: TControl;   //hint need learn about the child lists in here plus Parent prop!//   
  ComboBox: TcomboBox;
begin
  with Screen do begin     //  access the applications forms here
    for I := 0 to formCount - 1 do
      begin
        F := Forms;  // point F to form instance
        for C := 0 to F.ComponentCount - 1 do
          if F.Components[C] is TCombobox then
          begin
            ComboBox := F.Components[C] as TcomboBox;
            F.Show;
            F.BringToFront;
            ComboBox.Show;         The 'found' combo box instance is told to show //how? The ref has its address.//
            sleep(1200);
            caption := F.Name;
            ComboBox.Perform(CB_ShowdropDown,1,0);
            sleep(1200);
            ComboBox.Perform(CB_ShowdropDown,0,0);
            break;
          end;
      end;
  end;
end;
 

 

 

Edited by Pat Foley
added index to forms
  • Like 1

Share this post


Link to post
Posted (edited)
17 hours ago, Pat Foley said:

what happen at runtime when we are declaring some Objects ?

i mean exactly this Declaration 


vObj_Instance: TClass_Type; 

does this Allocate something in Memory ? or system resources ....

 

No it does not I think you want a reference.

YES IT DOES!

 

It allocatess space on the stack for a POINTER (assuming it's inside of a method).

 

When you say this:

vObj_Instance := TClass_Type.Create(...);

it allocates a chunk of memory from the heap, sets vObj_Instance to point to it, then calls the constructor with an implicit pointer argument to that chunk of memory and initializes it based on the code in the chain of constructors that get called.

 

If TClass_Type is defined as a RECORD, then it would allocate enough space on the stack to fit the entire record, and you would not need to allocate space for it from the heap.

 

In C/C++ this would be written as:

TClass_Type * vObj_Instance; // allocates space for a typed POINTER

// this is the constructor call equivalent to what happens in Delphi
vObj_Instance = new TClass_type(...); 

This is more clear, showing that it's a POINTER type.

 

In Dephi, the call to allocate space from the heap (by 'new' in C++) is always IMPLED.

 

Edited by David Schwartz
  • Like 1

Share this post


Link to post

 

 

The previous code I posted was based on Marco's Sydney book comments about changing event assignments at runtime. 

 

I think the OP is wanting to use reference.   Here is further example 

 

procedure TForm30.Button1Click(Sender: TObject);
var
    A: Double;
    ptrA: PDouble;
    ptrB: PDouble;
    ppB: PDouble;
    pC: PDouble;
    F, pF: TForm;
    refF: Tform;
begin

    new(ptrB);   //http://rvelthuis.de/articles/articles-pointers.html
    ptrB^ := 2.02; //initialize value in new instance location
    ppB := ptrB;   // second PDouble get address of first PDouble;
    Showmessage(ppB^.tostring);

    A:= 1.01;
    ptrA := @A;   // PDouble given address of double named A
    showmessage(ptrA^.tostring);

    pC := ptrB;   // Use reference to store pB value;
    ptrB^ := ptrA^; //overwrite pB with ptrA value
    ptrA^ := pC^; //overwrite ptrA data
    showmessage(ptrA^.tostring);

    // Delphi hides the explicit details of above in VCL
    // but accessing the properties of components can be done with above.
    F := TForm.create(self);
    pF := F;    // pF is reference no create needed!

    pF.Caption := 'EZ PZ';

    refF := pF;  // refF is a reference
    refF.Show;

    Dispose(ptrB);  //manual dispose
    //pF.free; commenting out allows new form each button click!
end;
 

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×