The project below fails to run with "access violation" error. I use Delphi XE2 Update 3.
program Project1;
{$APPTYPE CONSOLE}
type
TTestClass = class
public
class procedure Test;
end;
var
TestClass: TTestClass;
class procedure TTestClass.Test;
begin
end;
begin
TestClass.Test;
end.
If i mark class procedure Test as "static", there is no problem. Is this 'as designed'?
P.S.: It was my mistake, shame on me.
Yes, what you've witnessed is correct.
Non-static class methods, just like instance methods, have a hidden Self parameter. For class methods, that refers to the class reference. It's like the compiler transforms your method into this:
type
TTestClassClass = class of TTestClass;
procedure TTestClass_Test(Self: TTestClassClass);
When you call a class method on a non-class receiver (i.e., an object reference), the compiler inserts a call to ClassType to fill in that parameter with the run-time type of the object, like this:
TTestClass_Test(TestClass.ClassType);
The ClassType method fetches the address of the object's VMT, but your variable doesn't refer to any VMT. Your variable is either a null pointer or uninitialized, so attempting to dereference it to read the VMT address results in an access violation, if you're lucky. (If you're unlucky, it dereferences the address and the address happens to be somewhere else in your program's address space, and the result is interpreted as a VMT pointer even though it's not.)
Call class methods on class references or valid object references only.
TTestClass.Test;
When you call it on a class-reference "literal" as above, the compiler already knows the value of the first parameter and transforms the call like this:
TTestClass_Test(TTestClass);
Sounds reasonable. TestClass is nil. You cannot invoke a non-static class method on a non-instance:
'A class method can be called through a class reference or an object reference. When it is called through an object reference, the class of the object becomes the value of Self' - no object, no class.
'class static methods can be accessed without an object reference' - doesn't matter about the TestClass instance because of the direct, static call to the class method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With