Marius Gedminas wrote:
In Delphi you can declare a method 'virtual' or 'dynamic' and when you want to override it in an descendant class, you must do it with 'override' directive.
And what happens if you don't use "override"? Does it overload the methods then? (Does it have overloading at all?)
I think it's only needed for Delphi compatibility, where TObject is the ultimate ancestor of all objects. Perhaps another compiler switch (for Delphi compatibility)?
I agree (see below).
Peter Gerwinski wrote:
It's "class" = "reference to object". Fortunately, the GCC front-end is able to deal with such things,
Fine! :-) (Front-end? Or back-end?)
so we "only" have to implement the syntax into GPC - and take care that it doesn't break other applications of reference types such as `Var' parameters and procedural variables.
Yes. Are value and reference parameters of class type the same, then (in Delphi)? Or do reference parameters pass a pointer/reference to the reference, i.e. do they allow destroying and recreating the object?
Are pointers to classes allowed in Delphi, and what do they mean?
We should try to be compatible to Delphi and the ANSI Object Pascal draft.
Yes. And it would be even better if there was any documentation about them available... ;-) For Delphi, I don't have much hope since it's non-free, but Object Pascal? (Should I do another Yahoo search...? ;-)
Larry Carter wrote:
- All classes to have the same ultimate ancestor object.
When I actually started to think about this, I realized how this could be a problem. In Delphi, this commmon object works great becuase it provides all the basic machinery neccessary for all objects, however, this is machinery that is specific to the Intel running Windows environment, the memory model etc. An object of this type in GPC would probably be very bloated, making all its decedants bloated, becuase of all the different environments it would have to handle. Perhaps a library of foundation objects for each OS?? Especially since this really has little to do with the compiler itself anyway! :)
I think the problem we're facing is that Delphi is not really a "standalone" language, but partly tied to one special environment. Since for gpc, portability is a more important goal than conformance to other (non-standard) compilers, I agree that such things do belong into libraries.
AFAICG, objects in Delphi are typically things like windows, editors, dialogs and such "big things". Other use of OOP is for "small things" like vectors or certain data types with their operations which are completely independent of OS's and such.
The African Chief wrote:
Saves declaring those "PFoo" types, OTOH makes it impossible to declare global or local objects variables (without the overhead of allocating memory). If we have objects and classes, the programmer can choose what (s)he prefers.
Delphi also supports both Objects and Classes -
With the differences like I described them?
so it would be nice if we could as well.
gpc will certainly not remove objects when classes are implemented. :-)
[b] the constructor does the heap allocation stuff, e.g., "Foo := MyFoo.Create" *allocates memory for Foo "(New, Foo)" *calls Foo^.Create (constructor)
So it's the same as "Foo := New(MyFoo, Create)" in BP?
More or less.
I'd like to know it exactly. Is there any difference (besides the different syntax, of course)?
Delphi destroys all objects that it creates itself. However, if you manually create an object by calling its constructor, you have to destroy it yourself with a call to "Free".
Sounds logical. But when does Delphi create objects by itself? AFAIK, gpc doesn't do this yet, so we'd have to adopt this as well!?
I suspect that Delphi sets them to Nil as well, both before construction and after destruction - otherwise the checks for "Nil" made by TObject.Free would not make any sense, since there is nowhere in the source code where these things are manually set to Nil.
So I think gpc should do this as well, at least for references (to classes).
Probably so. However, Classes are different from "mere" objects, and I suspect that with Delphi, (assuming that Foo is an instance of a Class, and not of a mere object) if you do;
New(Foo); Foo.Create;
What "Foo" is pointing to may actually be undefined - and you will certainly get an exception when you try to do anything with "Foo".
If it's undefined in Delphi, it wouldn't hurt if there is a defined behaviour in gpc. :-)
In this case, it *is* necessary for Delphi compatibility. In Delphi all classes are descendants of TObject. Doing this in Delphi;
[...]
The VCL depends on this being so, and we should also support it (not least because Delphi programmers expect this to be so). This means of course that TObject then has to become part of the GPC RTS. For present purposes, it only needs to be something like this;
Sorry, but it probably can't be in the RTS, I think, because non-Delphi programs use the same RTS, and should not have this type.
My suggestion: implement a compiler switch like '--base-class="TObject"' so that gpc will use this class by default as a parent class if no parent is declared (and, of course, if the current class is not "TObject" itself ;-). With "--delphi", this switch could be set automatically. Then, TObject could be declared in some unit (like System for Delphi). (For "completeness", we could also have '--base-object' or so...)
BTW: This is similar to the '--uses="system"' I suggested -- things that are not really the job of the compiler, but needed for compatibility. Such switches seem to make the difference to the compiler as small as possible.
For BP/Delphi programs that are just recompiled with gpc, these switches can be used. When the programs are really ported to gpc, these things would probably put into them programs themselves, and the switches would not be used anymore (neither for native gpc programs), I guess.
Type TObject = Class Constructor Create; virtual; Destructor Destroy; virtual; Procedure Free; virtual; end; {I am not sure about the "virtual" bit}
{and any other (private) stuff needed for any compiler magic that we need to do;
The only magic field in gpc would be the "VMT" link.
Like I said, "Create" and "Destroy" are empty in TObject (i.e., they contain just an empty "begin end;" block). "Free" checks whether the pointer is Nil, and if it is not, it calls Destroy.
Nice little "trick", but not very systematic. "Free" is a method of an object, and this object can be "nil^"!? Technically, it works, but "Free" must not be virtual (I guess it isn't in Delphi)! But as a clean way, I'd prefer a procedure... (Or should we regard it as defined behaviour to call a static method of a non-existing object if the method doesn't access any fields of the object?)
Larry Carter wrote:
Saves declaring those "PFoo" types, OTOH makes it impossible to declare global or local objects variables (without the overhead of allocating memory). If we have objects and classes, the programmer can choose what (s)he prefers.
Delphi does not allocate memory for object variables untill the object is actually created with its create method.
Yes, I understood this. What I meant is, you can declare BP (and gpc) objects globally or locally (if you know the exact type at compile time), so they will be located in the data segment or on the stack, and no memory has to be allocated at all. (Just a minor optimization for most cases, but e.g. for small local objects in a frequently called procedure it could make a real difference.)
In Delphi, the common object ancestor (TObject) provides the most basic methods and properties that ALL objects need (creation, destruction, etc.). These are the methods/properties that are unlikely to be overridden (its rare that you would need a different destructor for example)
Sorry? I use different destructors all the time! E.g., if the object "possesses" other objects, it has to destroy them in its destructor.
Or did you mean another destructor of another name (but that's not overriding)?
and having a common ancestor provides the programmer with a ready to go foundation for his/her objects. I think a common ancestor is the right way to go.
Yes, for a library.
Ken kc7rad@vegasnet.net wrote:
Having the 'private' declarations visible anywhere within the unit in which it was defined is sort of a compatability thing with C++ 'friends'.
I had this suspicion, too. So I think, with "--borland-pascal", we should define the visibility like in BP. For the standard gpc mode, however, we should limit it to the class itself, and instead introduce friends like in C++ (one of the useful features of that language, IMHO).
Correct me if I am wrong, but a C++ class can be defined as being 'friends' with another class. Since they are 'friends', they can share certain properties. I personaly don't care for this. There are better ways of access properties in other classes! Plus this breaks the idea of 'object oriented' programming and provides a way around the OO paradigm.
Well, I haven't had a need for them in my BP programs (and haven't made use of the extended visibility in BP), but from some exercises I did in a C++ course, ISTR that they can be useful sometimes...
Right, only published propertied show up in the object inspector. I think for now, in GPC anyway, allow 'published' and treat it as a 'public'. When GPC moves to X-windows or gains a visual/graphical development tool, we should be able to utilize it better.
Good idea. However, what is this object inspector, anyway? To me, it sounded like a development tool, but now it seems like it's something used at runtime, right? What do programs do with it?