Al Boldi wrote:
Mattias Gaertner wrote:
"George Birbilis" <[EMAIL PROTECTED]> wrote:
X.Free
Should never fail since it's a class method and its implementation
checks if X is nil.
It's not a class method. It's a normal method. IMO this has been confused
several times in this thread. A class method has the 'class' keyword in
front of it.
type
TA = class
class procedure Fn;
procedure Foo;
procedure Bar; virtual;
end;
class procedure Fn;
begin
self.fn; // recursively calls itself like a normal function
end;
Here, self is not a pointer to an instance of TA, but to the class TA itself.
A class method looks like a normal procedure/function, but
- it gets /a class/ as a hidden 'self' parameter (this can be the class the method is
defined on, but also a descendant class!) (<--> normal methods get /an object/
as hidden self parameter)
- you can also call the class method like TA.Fn, or on an instance of a class,
like A.Fn; this will be translated to A.ClassType.Fn (note: A.ClassType is the
actual class type that A was created like)
- it obeys of course visibility specifiers like private and public (since its
part of a class definition)
Actually, class methods are methods of the class :)
The difference between a class method and a non-virtual method, is that a
non-virtual method has the ability to access a possibly invalid self. And
that's what makes it so dangerous.
Why do you consider it so dangerous? If a method is called on an invalid object
pointer, the caller is doing something wrong, don't you agree?
And what would you want to happen when a non-virtual method is called with an
invalid self? Should an exception be raised? (well if there was no check, you'd
likely get an exception as well) Or do you want the method to return
immediately, suppressing the erroneous condition in which the method was
called? The caller should really ensure that it calls a method on a valid
object. Also, the non-nil check can't guard against other invalid pointers, as
I said.
Sometimes, it might be an error if a non-virtual method is called on a nil
pointer, but in other cases there might be well defined behavior for that case,
such as for the Free method. Another example:
TAncestor = class
function ToString:string; virtual; // to be overridden be descendant classes
function ToStringSafe:string; // method that can even be called on nil pointer
end;
...
function TAncestor.ToStringSafe:string;
begin
if self=nil then Exit('<nil>');
Result:=ToString; // now it's safe to call the virtual method
end;
Also, it would give a performance penalty if the compiler would insert a
non-nil check in every non-virtual method. Allowing nil pointers gives more
flexibility to programmers.
Bram Kuijvenhoven wrote:
Michael Van Canneyt wrote:
If so, what side-effects would this cause when applied across the
complete class-hierarchy?
Blow up the size of you executable.
And a virtual method call is slower than a non-virtual call. (as it needs
to do a few lookups: class, VMT)
To ensure self is not nil, you can insert a check in a method itself.
However, you cannot defend yourself against an invalid (but non-nil)
object pointer. (I.e. a pointer to an object that is freed already.)
Is there a switch to pass to FPC to get a virtual method effect on
non-virtual methods, without incurring the VMT overhead?
No.
BTW virtual methods have not been introduced such that they wouldn't crash on
an invalid self, but to allow polymorphism, i.e. to allow descendant classes to
override behavior of a class.
Bram
_________________________________________________________________
To unsubscribe: mail [EMAIL PROTECTED] with
"unsubscribe" as the Subject
archives at http://www.lazarus.freepascal.org/mailarchives