[fpc-pascal] Understanding virtual methods

Xiangrong Fang xrfang at gmail.com
Tue Aug 20 07:34:48 CEST 2013


Hi Flavio,

Your findings confirmed mine, but not telling me why? It seems that the
"virtual" keyword has no use at all!   To confirm this, I just removed the
"inherited" call in TDerived, then re-run the program with or without
"virtual/override", the result is exactly same, i.e. with c2 (declared as
TBase), the following statements ALWAYS calls constructor of TDerived, NOT
TBase:

c2 := TDerived.Create;
c2 := TBase(TDerived.Create);

This is not same as the description in:
http://www.freepascal.org/docs-html/ref/refsu26.html

BTW, the above documents are talking about objects, but I am using classes,
is there any difference here?

Shannon



2013/8/20 Flávio Etrusco <flavio.etrusco at gmail.com>

> 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
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20130820/50bce9d0/attachment.html>


More information about the fpc-pascal mailing list