[fpc-pascal] Understanding virtual methods

Martin lazarus at mfriebe.de
Tue Aug 20 08:53:11 CEST 2013


On 20/08/2013 07:32, Xiangrong Fang wrote:
> Thanks.  Do you mean that the rules I see in the document apply to 
> NORMAL virtual methods, but not virtual constructors?
They apply to constructors too. But...

A virtual/overridden method is looked up based on the class used in code

TDerived.create; // the class given is TDerived

var
   b: TBase;
b := TDerived.create; // the class given still is TDerived

the assignment has nothing do to, what you class the method is called on.

b.Foo();  // Foo il looked up based on TBase

if b contains an instance of TDerived, then it depends on Foo being virtual.

>
> Also,  I have a related question:  it seems that to override methods 
> in ancestor it is required that the method has same signature, however 
> reintroduce will not have such limitations. Example:
>
> constructor TBase.Create; virtual;
> ... ...
> constructor TDerived.Create(AParam: TParamType); override
>
> The above code won't compile until I change the override keyword to 
> "reintroduce".  Because the compiler complains that there is no 
> Create() with the same signature in the base class.
>

Try to understand it on normal methods first. That is easier. 
(Technically it is the same for constructors, but you need a very 
abstract view, to realize this)

TBase = class
   procedure Foo; virtual;
...
TDerived = class
   procedure Foo; override;

var
   b: TBase;
d : TDerevied

WITHOUT virtual/overide
b := TDerived.Create

b.Foo; // will ca Foo declared on TBAse (because "b" is declared as TBase)
d.Foo // always call Foo from TDerived, because d can NOT contain a 
TBase anyway

WITH virtual/overide
b := TDerived.Create
b.Foo; // will call Foo declared on TDerived (because "b" is CONTAINS a 
TDerived)

ASSUMING (impossible) you wanted
   procedure Foo(a: String); override;

b.Foo; // should call Foo declared on either TFoo or TDerived, depending 
what was assigned to b
but if a TDerived was assigned, then it would break, because there is no 
argument.

so this is impossible

> However, if I use reintroduce, according to the document, the compiler 
> will make the Create method STATIC and hide the create method in the 
> base class, in another word, it is then invalid to call  
> TDerived.Create; (without param).    What is the mechanism here??   
> Also, if I do not use override or reintroduce, instead, put an 
> "overload" there, it will make BOTH version of the constructor 
> visible,   AND the "inherited" keyword also works well!

"reintroduce" is just a way to get rid of the warning, indicating that 
you did not accidental use the same name as in the base class




More information about the fpc-pascal mailing list