[fpc-pascal] Understanding virtual methods

Flávio Etrusco flavio.etrusco at gmail.com
Tue Aug 20 06:16:24 CEST 2013


On Mon, Aug 19, 2013 at 10:44 PM, Xiangrong Fang <xrfang at gmail.com> wrote:
> Hi All,
>
> I am reading this document:
> http://www.freepascal.org/docs-html/ref/refsu29.html   and doing an
> experiment with the following code:
>
> program project1;
> {$mode objfpc}{$H+}
> type
>   TBase = class
>     constructor Create; virtual;
>   end;
>   TDerived = class(TBase)
>     constructor Create; override;
>   end;
>
> var
>   c1, c2: TBase;
>   c3: TDerived;
>
> constructor TDerived.Create;
> begin
>   WriteLn('Entering TDerived.Create');
>   inherited Create;
>   WriteLn('Leaving TDerived.Create');
> end;
>
> constructor TBase.Create;
> begin
>   WriteLn('Entering TBase.Create');
>   Writeln('Leaving TBase.Create');
> end;
>
> begin
>   WriteLn('Creating a TBase and assigning to TBase variable...');
>   c1 := TBase.Create;
>   WriteLn('Creating a TDerived and assigning to TBase variable...');
>   c2 := TDerived.Create;
>   WriteLn('Creating a TDerived and assigning to TDerived variable...');
>   c3 := TDerived.Create;
> end.
>
>
> The problem is, it makes NO DIFFERENCE at all in the following cases:
>
> CASE 1:
>
> TBase.Create;
> TDerived.Create;
>
> CASE 2:
>
> TBase.Create; virtual;
> TDerived.Create; virtual;
>
> CASE 3:
>
> TBase.Create; virtual;
> TDerived.Create; override;
>
> According to the document, "inherited" cannot be used in non-virtual
> methods,

At least that's the result I would expect :)
I can confirm your findings; contrary to the documentation, a simple
test works correctly (the compiler prints no warnings or hints, both
method and constructor work correctly, calling either a non-virtual
from virtual, and virtual from non-virtual).


> and it is wrong to use virtual in sub-class.

It doesn't say that, it simply says that the redeclaration will not
override the base implementation (the different behavior for 'object'
is news to me!).

FWIW your test doesn't actually "exercise" inheritance, since virtual
constructors only make a difference when you call from a class
reference (similarly, you'll only see a difference in virtual methods
when calling from a base-typed variable).

Code>>>
var MyClass: TComponentClass = TDataModule;
begin
  MyClass.Create(nil);
<<<

will instantiate a TDataModule.

Code>>>
var MyControl: TControl;
begin
  MyControl := TButton.Create;
  MyControl.ExecuteDefaultAction;
<<<

will invoke TButton's implementation of ExecuteDefaultAction.

> But my test shows the  contrary.   BTW, I am running Linux on 64bit platform.
>
> Regards,
> Shannon

Best regards,
Flávio



More information about the fpc-pascal mailing list