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

Reply via email to