Recent

Author Topic: OOP structures in fpc and Lazarus  (Read 15437 times)

ArtLogi

  • Full Member
  • ***
  • Posts: 175
Re: OOP structures in fpc and Lazarus
« Reply #15 on: November 10, 2021, 09:52:16 pm »

"OOP structures in fpc and Lazarus"
I like the OOP in fpc, I haven't posted much OOP, but I am working away in the background.
But not being a Lazarus ide user (very much), is there a difference in OOP between the two?
Lazarus also uses fpc as the compiler, so it is not necessary to mention Lazarus when discussing language features (IMHO). 

Lazarus does provide a lot of editorial help that makes it easier and faster to create and maintain classes (and objects, advanced records...) e.g. by creating empty methods in the implementation section that corresponds to methods declared in a class, synchronization of parameters between interface and implementation and so forth.

Edit: I see @jollytall was a bit quicker to post...
Even though I'm total noob, there is compiler directive to lazarus (FPC____) vs FPC, which kind of makes it kind of also if not language feature, at least local dialect.

Thank you for the learning resorce I will read it.
While Record is a drawer and method is a clerk, when both are combined to same space it forms an concept of office, which is alias for a great suffering.

PascalDragon

  • Hero Member
  • *****
  • Posts: 3639
  • Compiler Developer
Re: OOP structures in fpc and Lazarus
« Reply #16 on: November 11, 2021, 09:16:14 am »
Even though I'm total noob, there is compiler directive to lazarus (FPC____) vs FPC, which kind of makes it kind of also if not language feature, at least local dialect.

What do you mean? The $Mode directive with Lazarus setting it to ObjFPC by default? That has nothing to do with Lazarus, but it's a functionality of FPC to allow different language modes per unit (the main ones are ObjFPC and Delphi). In the default mode most Object Pascal related functionality is disabled (e.g. classes).

MarkMLI I think is right, but that is not the point. So, before it turns into a religious war, I ask my second question (and still hope, someone can shed some light on Q1).

Q2. Why is there a static keyword needed for an advanced record class level method?
The good news is that it is at least coherent with the object approach, i.e. a class procedure X; static; can be called with the type tTest.X and there is no Self available.
On the other hand I do not understand why is it implemented this way. To me two ways would be logic:
EITHER
it would be similar to object, but then why not to allow class procedure X; (without static) and procedure X; static; (without class) with slightly different behavior?
OR
accept the fact that record is different than object and in record there is only one way to make a method class level, but then why need to use static at all? Using only class procedure X; would be in line with the record field declaration where there is only one way to define with class var (unlike the object where static is also allowed to define a field, but that is another question).

Short answer: because that's how Delphi did it.

Long answer: Delphi used the same syntax that is used for static methods inside classes also for records. In classes you either have a class method using class procedure or class function (which takes the class type as Self parameter and can also be virtual) or a static class method if you append the static modifier (in which case there is no Self). Now, Delphi doesn't really acknowledge object at all (considering it deprecated and such) and thus they simply used the syntax they know to also implement it for records when they implemented advanced records.
By the way: the correct syntax in an object declaration is without the class keyword, but with the static modifier. That is because the object type stems from a time before classes were introduced, thus also before the introduction of the class keyword. FPC also allows the syntax from the class type simply because both objects and classes share a lot of code and sometimes objects gain functionality introduced for classes simply by accident.

jollytall

  • Full Member
  • ***
  • Posts: 158
Re: OOP structures in fpc and Lazarus
« Reply #17 on: November 11, 2021, 01:21:52 pm »
Short answer: because that's how Delphi did it.

Long answer: Delphi used the same syntax that is used for static methods inside classes also for records. In classes you either have a class method using class procedure or class function (which takes the class type as Self parameter and can also be virtual) or a static class method if you append the static modifier (in which case there is no Self). Now, Delphi doesn't really acknowledge object at all (considering it deprecated and such) and thus they simply used the syntax they know to also implement it for records when they implemented advanced records.
By the way: the correct syntax in an object declaration is without the class keyword, but with the static modifier. That is because the object type stems from a time before classes were introduced, thus also before the introduction of the class keyword. FPC also allows the syntax from the class type simply because both objects and classes share a lot of code and sometimes objects gain functionality introduced for classes simply by accident.

Thanks PascalDragon,
although I still do not find it a complete answer.

The short answer is clear, but that would lead to two second questions:
- why did Delphi do it like this? I know it is beyond this forum to guess, but Embarcadero guys are also very smart, so surely they had either a good reason or a history behind.
- why is it the same in every mode? If you see the still open Q1 I had earlier, I feel a bit of confusion among compiler modes and modeswitches, but what is clear that different modes can accept or reject different syntax. So, even if it is the case in mode delphi, I do not see why it is still the same in mode objfpc + modeswitch advancedrecords.

From the long answer I again learnt something, that the class keyword only appeared with the class type and since object is older than class, object should not use the class procedure type definition. Btw. I use in my doc the terms "class level field, class level method", even in object. I hope it is still the correct terminology.

Also your long answer leads us to my third question:

Q3. Why does a static method in an object has Self?
I did not find any documentation for object, but I found it for class, where it states what you also write, i.e. that the static keyword makes the call without Self. It is impossible to test static alone for class, as class does not allow only static without class in front of procedure. When class procedure X; is used then it has Self, but with static; added it has not got Self. But this is almost my Q4 later, so back to object and Q3:

In object (chapter 5.3 in my doc) all the four definitions are possible (I only write procedure, but also function works the same).
Code: Pascal  [Select][+][-]
  1. procedure PNothing;
  2. procedure PStatic; static;
  3. class procedure PClass;
  4. class procedure PClassStatic; static;

The first is easy, but the other three are all some sort of class level methods. Based on the logic described above for class, I would expect that here (i.e. object) the two with the static; keyword have no Self. But it is not the case; PStatic happily has a Self, only the last one is without.
My expectation was that using the class procedure part makes it callable as tMyObject.P, while if class is not in front of it then only MyObject.P can be called, while using or not static; makes only the list of arguments different with or without Self, but it is not the case. Is it a bug?
Last, this also contradicts a bit to your answer regarding the "correct syntax". If one only uses (I am still at object!) the PStatic method from above as you suggest, then one cannot use the tMyObject.P logic, what might be handy sometimes, e.g. if we do not want to make an instance at all (equivalent of making sure that regardless how many instances are declared they all behave as the same one, i.e. only class level fields and methods are declared).

So my - might be wrong - conclusion is that for object the best is to use class procedure PClass;, for class level methods. PClass has a benefit over PStatic as it can be called from the type, while PStatic cannot AND PClass also has a benefit over PClassStatic as it always has a Self, even if we do not want to use. Is it a wrong assumption?

PascalDragon

  • Hero Member
  • *****
  • Posts: 3639
  • Compiler Developer
Re: OOP structures in fpc and Lazarus
« Reply #18 on: November 11, 2021, 02:07:19 pm »
- why did Delphi do it like this? I know it is beyond this forum to guess, but Embarcadero guys are also very smart, so surely they had either a good reason or a history behind.

I explained that in my long answer (emphasis mine):

Now, Delphi doesn't really acknowledge object at all (considering it deprecated and such) and thus they simply used the syntax they know to also implement it for records when they implemented advanced records.

- why is it the same in every mode? If you see the still open Q1 I had earlier, I feel a bit of confusion among compiler modes and modeswitches, but what is clear that different modes can accept or reject different syntax. So, even if it is the case in mode delphi, I do not see why it is still the same in mode objfpc + modeswitch advancedrecords.

Because there is no reason to change something just for the sake of changing it. Advanced records were introduced mainly for compatibility with Delphi (and they're really handy inside generics). Adding separate syntax is only done when really necessary or beneficial (e.g. introducing and using type helper for all kinds of helpers instead of abusing record helper for primitive types and who-knows-what for interface types). This is not the case for advanced records. Also any bit of additional syntax added to the compiler increases the burden when maintaining the compiler.

From the long answer I again learnt something, that the class keyword only appeared with the class type and since object is older than class, object should not use the class procedure type definition. Btw. I use in my doc the terms "class level field, class level method", even in object. I hope it is still the correct terminology.

I personally differentiate between instance and static fields/methods.

Q3. Why does a static method in an object has Self?
I did not find any documentation for object, but I found it for class, where it states what you also write, i.e. that the static keyword makes the call without Self. It is impossible to test static alone for class, as class does not allow only static without class in front of procedure. When class procedure X; is used then it has Self, but with static; added it has not got Self. But this is almost my Q4 later, so back to object and Q3:

In object (chapter 5.3 in my doc) all the four definitions are possible (I only write procedure, but also function works the same).
Code: Pascal  [Select][+][-]
  1. procedure PNothing;
  2. procedure PStatic; static;
  3. class procedure PClass;
  4. class procedure PClassStatic; static;

The first is easy, but the other three are all some sort of class level methods. Based on the logic described above for class, I would expect that here (i.e. object) the two with the static; keyword have no Self. But it is not the case; PStatic happily has a Self, only the last one is without.
My expectation was that using the class procedure part makes it callable as tMyObject.P, while if class is not in front of it then only MyObject.P can be called, while using or not static; makes only the list of arguments different with or without Self, but it is not the case. Is it a bug?
Last, this also contradicts a bit to your answer regarding the "correct syntax". If one only uses (I am still at object!) the PStatic method from above as you suggest, then one cannot use the tMyObject.P logic, what might be handy sometimes, e.g. if we do not want to make an instance at all (equivalent of making sure that regardless how many instances are declared they all behave as the same one, i.e. only class level fields and methods are declared).

So my - might be wrong - conclusion is that for object the best is to use class procedure PClass;, for class level methods. PClass has a benefit over PStatic as it can be called from the type, while PStatic cannot AND PClass also has a benefit over PClassStatic as it always has a Self, even if we do not want to use. Is it a wrong assumption?

No one said that the compiler is bug free.

The correct syntax for object is procedure Name; static. Definitely wrong is class procedure Name; (because there is no meta object type equivalent to TClass) and consequently class procedure Name; static; should be disabled as well simply because objects stem from TP times and there the class keyword was not known.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 9769
  • FPC developer.
Re: OOP structures in fpc and Lazarus
« Reply #19 on: November 11, 2021, 04:07:35 pm »
I think Pascaldragon hits the core of the issue: forget about old TP objects. Adding them into feature discussion mix only clouds the picture. These haven't seen feature expansion (other than fixing trivialities like automated types embedded in them) since TP 7 in 1994 or so, and thus were never really a factor. Delphi 2 in 1996 added classes effectuating the deprecation, now 25 years ago.

As to why that is the case, I can only speculate, but there was quite some frustration about the VMT pointer automatically appearing in TP times. From a type definition alone you can't determine if it has a VMT, you have to trace the hierarchy to find out if it declared virtual methods somewhere.

Another factor is that they might have wanted to deprecate it earlier, but it simply didn't happen because the focus was usually on more enterprise oriented features/things rather than base syntax.

When Classes emerged it was considered dead, and maybe that decision (to replace the class stheir .NET and Objective C hosted adventures only confirmed that.

Later (2006-7) during the .NET adventures, implementing generics (first a .NET(2) only feature in D2007) probably triggered expansion of the record concept.  Because for generics specialized with records they needed operators and iterating (FOR...IN) to be bundled with the record, preferably as close to modern languages (.NET ,Java at the time) as possible, because Microsoft kept declaring till 2008-9 that native was dead.

Somehow the implementation of that, advanced records got delivered before (D2006)  the feature they were intended for, generics (D2007).


jollytall

  • Full Member
  • ***
  • Posts: 158
Re: OOP structures in fpc and Lazarus
« Reply #20 on: November 11, 2021, 04:31:50 pm »
@PascalDragon
Thanks, it is very useful. I will do some updates in my doc.

Still few things to further clarify:
I personally differentiate between instance and static fields/methods.

In the old days I also followed this naming, but then I got confused. In class, one can have class procedure PClass; and class procedure PClassStatic; static;. None of these two are "Instance methods", so as per your naming they are "Static methods", but only one of them is Static (no Self) the other is not. The common thing in these two, is the class keyword, hence I used the "class level method', to refer to them, but not plainly calling it "class method" to allow the naming work for object or record as well.
The other way would be to use instance/static for record and object, and instance/class for class.

If one only uses (I am still at object!) the PStatic method from above as you suggest, then one cannot use the tMyObject.P logic, what might be handy sometimes, e.g. if we do not want to make an instance at all (equivalent of making sure that regardless how many instances are declared they all behave as the same one, i.e. only class level fields and methods are declared).

So my - might be wrong - conclusion is that for object the best is to use class procedure PClass;, for class level methods. PClass has a benefit over PStatic as it can be called from the type, while PStatic cannot AND PClass also has a benefit over PClassStatic as it always has a Self, even if we do not want to use. Is it a wrong assumption?
Apparently I got confused even reading my own document (there in chapter 5.3 it was correct). So, just to put it straight:
In case of object, all class level methods can be defined three ways (procedure PStatic; static;, class procedure  PClass; and class procedure PClassStatic; static;).
The two static can be called as tMyObejct.Method, the one without static cannot.
The static without class is the traditional object structure and the other two has no benefit at all.
The static without class has a Self parameter unlike it is used in class, where static hasn't got a Self (there only class procedure X; static; can be static, without class, static alone is not even allowed).

I do not fully understand your reasoning, why the lack of meta object type should prevent using class procedure PClass; for object. But to me it is totally logic to say that the class keyword was invented later and it only works in object because object and class share some codebase in the compiler, but none of the two definitions starting with class, as above I corrected myself, have any advantages over the original procedure PStatic; static; definition.
Is it correct to say, or is it a stretch, that class keyword does not exist in object officially, so using class var FieldName and class procedure with or without static is only an abuse of the compiler's current behavior resulted from the shared codebase and it is not even guaranteed to work the same way?

@marcov
Thanks for the detailed explanation. I do not want to take a position whether object is dead or not. I saw people reasoning why a stack based structure is sometimes better than a heap pointer. One (like Delphi) can also say that for that you now have advanced record, but many feel that it is only an extra (even in mode objfpc need a modeswitch to use) and not a "core" solution.
My whole purpose of writing the doc was to clarify what is possible, what is not, and how to do that. So, we might say that object is dead, but as long as people use it, it is only half dead. I was (or at some smaller points still am) confused on the three animals (record, object, class), so I tried to collect all my questions in one place.
Now, based on PascalDragon's reply, I think I have peace in my mind regarding object, can clarify my doc and then object can live on in its own place.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 9769
  • FPC developer.
Re: OOP structures in fpc and Lazarus
« Reply #21 on: November 11, 2021, 05:52:41 pm »
@marcov
Thanks for the detailed explanation. I do not want to take a position whether object is dead or not. I saw people reasoning why a stack based structure is sometimes better than a heap pointer.

Any construct has its proponents. But it is a fact that objects haven't had any major new features since 1994.

I wanted to warn against taking such talk to seriously, since when advanced records were planned/added, TP objects probably never were on the table as a possible solution.

Quote
One (like Delphi) can also say that for that you now have advanced record, but many feel that it is only an extra (even in mode objfpc need a modeswitch to use) and not a "core" solution.

I'm no fan of mode objfpc, so I don't spend much attention to it. The reasons behind its design choices seem random to me. (as an older core member I do know some of original argumentations on a per feature basis, but I never saw much of a pattern in it)

Quote
My whole purpose of writing the doc was to clarify what is possible, what is not, and how to do that. So, we might say that object is dead, but as long as people use it, it is only half dead. I was (or at some smaller points still am) confused on the three animals (record, object, class), so I tried to collect all my questions in one place.

Note that TP Object is not deprecated in Free Pascal, mostly for the benefit of TP compatibility and the textmode IDE. Also Lazarus has/had some use of it (e.g. TLazIntfImage)

As far as why Delphi went with advanced methods, I tried to explain possible reasons why TP objects probably were not on the table. (long term legacy and backwards compatibility concerns, and a automatic VMT feature that had itscritics).

How you weave these things into your document, is your concern, but keep in mind that the opinion that they might as well have revived TP objects is not widely supported.
« Last Edit: November 11, 2021, 06:40:57 pm by marcov »

kupferstecher

  • Sr. Member
  • ****
  • Posts: 470
Re: OOP structures in fpc and Lazarus
« Reply #22 on: November 11, 2021, 07:49:34 pm »
Hello jollytall,

thanks for sharing! I just read it and have some remarks.

1. You chose the sequence record - advanced record - object - class
 For people learning OOP in my opinion this is not the best order. I'd choose the following order:
record - class - advanced record - object

When I leared OOP in FreePascal some years ago I found a tutorial in the internet that looked good and (although for Delphi) I worked it through. In the end it said object is deprecated, but class works nearly the same... For a beginner a bit frustrating.

2. About the memory locations, you distinguish between stack and heap. Although you mention the special situation of global variables, I think this is easily misunderstood. So I'd distinguish between three types of memory: the Static Memory for global variables, the Stack where local variables are saved and the Dynamic Memory (Heap) for runtime data.
Records and Objects save their fields directly in the static memory (globals) or Stack (locals), and can be saved in the Heap only with the use of pointers. The variables of classes in contrast only carry the address of the data fields that are allocated on the heap when calling the constructor.

3. You could mention what explicitely happens, when the constructor is called (Perhaps I just overread something).
MyClassInstance := tMyClass.Create;

tMyClass.Create calls the constructor of tMyClass. Therefore the compiler inserts some code to allocate the required memory for the class instance on the heap, initializes all variables, initializes the VMT if neccessary, calls the code of the 'constructor' and returns the memory address, which is then assigned to MyClassInstance.

4. About inheritance, you talk about the "closest" procedure that is called when useing virtual/override. I would add, that for overriding a procedure without virtual/override, the procedure to be called is determined on compile time and directly uses the type of the variable to determine which procedure to call. When using virtual/override, the procedure to be called is determined at runtime, according to the (derived) type that the instance actually has, 'independent' of the type that the variable has (but of course has to be of a derived type).

Regards

jollytall

  • Full Member
  • ***
  • Posts: 158
Re: OOP structures in fpc and Lazarus
« Reply #23 on: November 11, 2021, 09:54:28 pm »
@kupferstecher

Thanks you for your comments. My comments, replies:

1. I was hesitating a bit on the sequence. Historically record, object, class, advanced record would have been the best. For current popularity and usability, probably class, record, advanced record, object would have been it. I chose the logic of complexity, features from the simplest to the most advances, i.e. record, advanced record, object, class. I don't think any is much better than the other. I think it is complex and due to different teams following different routes, there is no clear sequence of logic.
I agree that it is frustrating (not only for a beginner), this is why I tried to collect the questions I had.

2. Good point to highlight more when the memory allocation is done. I will try to rephrase it a bit. What you write is mainly correct and I tried to write the same in 3.5, also mentioning some other computer systems with different memory management tools, where I have very limited knowledge though.
What you do not mention, and if I go into these details I will have to add, although hidden somewhere among the lines it is there, that even for record and class types the class level (a.k.a. static) fields are reserved at compile time. What I do not know, but will have to investigate, what happens if a type is declared locally (nested type). Are the class level fields of them reserved in the static memory at start-up, or they only get allocated when the given code comes into scope, e.g. when a procedure is called? Also I will explain more that for classes the class constructors are called automatically (mentioned in 5.3 source code) and class level fields are reserved automatically. Here again I do not know, when exactly and where these fields are placed? Are they in the Heap like class instance fields or like global variables? If you know it, I would be glad if you could share, so I can include.
What my warning anyway, that due to the logic of Pascal, it should not really be a top priority for a programmer to go into the details of memory usage. Unless there is a special reason, I think the compiler takes care good enough.

3. Yes, I shall mention a bit more of it. I covered a bit this topic in 5.10 where I talked about fail, but I agree, it deserves a bit more (albeit it is well documented elsewhere, so I never had a question about it).
I also thought to mention more details about the virtual table, as that is an interesting topic in itself, how the "simple" VMT of object is structured vs. the more complex and better documented VMT of class.

4. I thought I covered that it great details, starting in 5.6 for object and even more, with all the ways to reintroduce and start a new virtual tree in class in 6.7. I might use a bit more the language of compile time and run time. What else do you miss there?

Thanks again,

VTwin

  • Hero Member
  • *****
  • Posts: 1087
  • Former Turbo Pascal 3 user
Re: OOP structures in fpc and Lazarus
« Reply #24 on: November 11, 2021, 09:58:48 pm »
As has been pointed out, objects are basically deprecated. Some folks still use them, but if I was learning I would pass over them.
“Talk is cheap. Show me the code.” -Linus Torvalds

Free Pascal Compiler 3.2.2
macOS 10.13.6: Lazarus 2.2.0 (64 bit Cocoa)
macOS 12.0.1: Lazarus 2.2.0 (64 bit Cocoa M1)
Ubuntu 18.04.3: Lazarus 2.2.0 (64 bit on VBox)
Windows 7 Pro SP1: Lazarus 2.2.0 (64 bit on VBox)

kupferstecher

  • Sr. Member
  • ****
  • Posts: 470
Re: OOP structures in fpc and Lazarus
« Reply #25 on: November 11, 2021, 11:31:46 pm »
Hello jollytall,

my suggestions were mostly on how to make it more clear to the reader, I think you already had the important topics covered. So it's more about how to describe the things.

To 1. I know rearranging is a lot of effort, so...
 
For current popularity and usability, probably class, record, advanced record, object would have been it.
I'd begin with record, as that is known by most programmers and a good basis to discuss classes. Also a programmer really needs to know/learn about records, but about object and advanced records I wouldn't say that. (Although in circumstances I use the object type myself).

To 2.
Quote
and I tried to write the same in 3.5, also mentioning some other computer systems with different memory management tools, where I have very limited knowledge though.
Yes, I recognized that. As said, I didn't consider anything wrong, its just a reader may focus too much on the stack. In the cases I personally use objects (not classes) they are never instantiated in local variables, so the whole stack thing doesn't apply there. Seems sometimes Stack is used in contrast to the Heap and actually means stack + static memory.
Quote
[...] that even for record and class types the class level (a.k.a. static) fields are reserved at compile time.
Never thought about that :)

Quote
what happens if a type is declared locally (nested type)
What do you mean by that? Classes can't be procedure-local, can they?

Quote
Also I will explain more that for classes the class constructors are called automatically (mentioned in 5.3 source code) and class level fields are reserved automatically. Here again I do not know, when exactly and where these fields are placed? Are they in the Heap like class instance fields or like global variables?
Perhaps that would be too detailed and of not much interest. As you said the compiler takes care of it. And I also don't know :) but believe they are allocated like global variables. I don't know if they are automatically zeroed like 'standard' fields.

To 4. Yes, your description is very detailed, my proposal was just to point out the compile-time/runtime difference to make the concept clearer.

--
Regards

jollytall

  • Full Member
  • ***
  • Posts: 158
Re: OOP structures in fpc and Lazarus
« Reply #26 on: November 12, 2021, 08:42:30 am »
Quote
what happens if a type is declared locally (nested type)
What do you mean by that? Classes can't be procedure-local, can they?
Well, I did not know what happens as I had never tried that. Now I checked and so I know: You cannot do that, its a compile time error. One problem less. Thanks.

And I also don't know :) but believe they are allocated like global variables. I don't know if they are automatically zeroed like 'standard' fields.
It is difficult to test, since when the program starts it gets its memory that can easily be zero anyway. Anyway, I will make some test.
What I know though is, if you explicitly define a class constructor, that is called before the actual unit starts (as said later, units also run, if they have a begin end or initialization end section). I therefore assume that a default class constructor is called even if no one defined.

Thaddy

  • Hero Member
  • *****
  • Posts: 11125
Re: OOP structures in fpc and Lazarus
« Reply #27 on: November 12, 2021, 09:23:32 am »
I therefore assume that a default class constructor is called even if no one defined.
If you mean that a class definition with a class constructor, that is correct and documented.
It is not an assumption but a fact.
Note that the wiki errs at many points, but the manual explains this very well.
https://www.freepascal.org/docs-html/ref/refsu29.html

I.e: "The class constructor/destructor is called irrespective of the use of the class"

Again an example of Read The Friendly Manual...... (Oh, well:  >:D >:D >:D >:D >:D)
Forgot about that.... :P Could have done with two less devils... Did I use them this year?.. ::)
« Last Edit: November 12, 2021, 09:45:47 am by Thaddy »
You have morons, I am one, and you have morons squared.

jollytall

  • Full Member
  • ***
  • Posts: 158
Re: OOP structures in fpc and Lazarus
« Reply #28 on: November 12, 2021, 09:52:35 am »
No, it is not what I meant. I had read the manual, especially this part, before I wrote my doc. I wrote in my doc as well as in the last post, that if a class constructor is defined it is called automatically. It is clear from my tests and from this manual.
(I used the word, the class constructor is defined, not the word created, as used in the manual. This was to avoid confusion, though it might caused more. To me created means when we do create something and that is typically with a verb Create, what happens to be the constructor's name for class. Define is more that we write the code, so the class constructor exists.)

So the question was from kupferstecher, whether all class fields are zerod out when no class constructor is defined? When a class instance is instanciated (created) it can only be done through using the constructor, what is always available as derived from TObject, even if we do not redefine it. That in itself zeros out the instance fields.
But I did not find any documentation whether a class constructor is inherited from TObject and whether that is called automatically, or there is no guarantee that class fields are zero. The linked doc says that class constructor can be created (defined) to initialize class fields. But is it needed to zero them, or zero is already ensured?
It is difficult to test, as in a modern, large memory PC, the memory area used can easily be zero even without initialization.

Thaddy

  • Hero Member
  • *****
  • Posts: 11125
Re: OOP structures in fpc and Lazarus
« Reply #29 on: November 12, 2021, 09:58:04 am »
But is it needed to zero them, or zero is already ensured?
In principle the answer is yes. The exception is overriding NewInstance.
https://www.freepascal.org/docs-html/rtl/system/tobject.newinstance.html

BTW all this is documented as well.....(oh, well, go ahead... >:D 8-))

Explanation: NewInstance/ultimately InitInstance zeros out the memory for you.

Aside question: why do you not read the sources? They are free!
« Last Edit: November 12, 2021, 10:04:51 am by Thaddy »
You have morons, I am one, and you have morons squared.

 

TinyPortal © 2005-2018