bravesofts 6 Posted October 4, 2021 (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 October 4, 2021 by bravesofts Share this post Link to post
FPiette 384 Posted October 4, 2021 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/ 2 Share this post Link to post
bravesofts 6 Posted October 4, 2021 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
David Schwartz 426 Posted October 4, 2021 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'. 1 Share this post Link to post
David Schwartz 426 Posted October 4, 2021 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. 1 Share this post Link to post
David Schwartz 426 Posted October 4, 2021 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 1 Share this post Link to post
bravesofts 6 Posted October 4, 2021 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
David Schwartz 426 Posted October 4, 2021 (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 October 4, 2021 by David Schwartz 1 Share this post Link to post
Dalija Prasnikar 1397 Posted October 4, 2021 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; 1 Share this post Link to post
FPiette 384 Posted October 4, 2021 (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 October 4, 2021 by FPiette 1 Share this post Link to post
Pat Foley 51 Posted October 4, 2021 (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 October 4, 2021 by Pat Foley added index to forms 1 Share this post Link to post
David Schwartz 426 Posted October 5, 2021 (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 October 5, 2021 by David Schwartz 1 Share this post Link to post
David Schwartz 426 Posted October 5, 2021 This is a link to a section on this site where you can download a free copy of Marco's book: https://en.delphipraxis.net/topic/4418-object-pascal-handbook-delphi-104-sydney-edition-marco-cantù-2020-571pg/ 1 Share this post Link to post
Pat Foley 51 Posted October 6, 2021 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; 1 Share this post Link to post