[gelöst]Überschreiben von virtual static Methoden

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

[gelöst]Überschreiben von virtual static Methoden

Beitrag von hubblec4 »

Hallo Lazarus Gemeinde

Wie der Titel schon sagt wollte ich gern eine virtuelle statische Methode( genauer gesagt eine Funktion) in einer abgeleiteten Klasse überschreiben.

Soweit funktioniert das eigentlich auch.

https://www.freepascal.org/docs-html/ref/refsu28.html
Hier steht ja auch:
Note that class methods can be virtual, and can be overridden.

Jedoch funktioniert das anscheinend nur "teilweise", da in meinem Projekt ein Fehler auftritt, da nicht die abgeleitete Funktion verwendet wird.

Ich habe dann im Web gesucht und leider nur sehr wenig Infos bekommen. Genau genommen keine die mein Problem gelöst hat.

Daher habe ich dann mal ein kleines Test programm geschrieben, welches deutlich zeigt das virtuelle statische funktionen zwar überschrieben werden aber nicht immer verwendet werden.

Code: Alles auswählen

program Virtual_Static_Methods;


type

 { TBase }

 TBase                  = class
  public
   class function StaticFunction: Boolean; virtual; static; 
   class function GetValueOfStaticFunction: Boolean; static;

   function NormalFunction: Boolean; virtual;
   function GetValueOfNormalFunction: Boolean;
 end;


 { TDerived }

 TDerived               = class(TBase)
  public
   class function StaticFunction: Boolean; override; static;
   function NormalFunction: Boolean; override;
 end;





{ TBase }

class function TBase.StaticFunction: Boolean;
begin
  Result:=false;
end;
     
class function TBase.GetValueOfStaticFunction: Boolean;
begin
  Result:=StaticFunction;
end;

function TBase.NormalFunction: Boolean;
begin
  Result:=false;
end;

function TBase.GetValueOfNormalFunction: Boolean;
begin
  Result:=NormalFunction;
end;
       



{ TDerived }

class function TDerived.StaticFunction: Boolean;
begin
  Result:=true;
end;

function TDerived.NormalFunction: Boolean;
begin
  Result:=true;
end;



var
  Base: TBase;


begin
  WriteLn('Test virtual static methods');

  Base:=TDerived.Create;

  Write('call Base.StaticFunction: ');
  WriteLn(Base.StaticFunction);                  // liefert TRUE
  Write('call Base.GetValueOfStaticFunction: ');
  WriteLn(Base.GetValueOfStaticFunction);        // liefert FALSE


  Write('call Base.NormalFunction: ');
  WriteLn(Base.NormalFunction);                  // liefert TRUE
  Write('call Base.GetValueOfNormalFunction: ');
  WriteLn(Base.GetValueOfNormalFunction);        // liefert TRUE


  Base.Free;
  ReadLn;
end.
Wird die überschriebene statische Funktion direkt aufgerufen dann liefert sie das Ergebnis TRUE.
Allerdings wird bei der GetValueOfStaticFunction Funktion nicht die abgeleitete Funktion StaticFunction verwendet. Daher ist das Ergebnis dann FALSE.

Als Gegen-Test gibt es noch eine nicht-statischte (normale) Function. Hier wird immer die abgeleitete Funktion verwendet.


Ist das so beabsichtigt oder ist es ein bug?
Zuletzt geändert von hubblec4 am So 23. Mai 2021, 17:50, insgesamt 1-mal geändert.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Überschreiben von virtual static Methoden

Beitrag von fliegermichl »

Also wenn ich mir das hier durchlese, dann können Methoden die als static deklariert werden nicht virtual sein.
https://www.freepascal.org/docs-html/ref/refsu30.html

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Überschreiben von virtual static Methoden

Beitrag von hubblec4 »

Mmmh... ja dort steht das sie nicht virtual sein können,
aber sie können es doch sein und auch das überschreiben klappt ja,
wie man an meinem test programm sehen kann.

Und in dem Link von mir steht ja auch das sie virtual sein können.

das scheint also irgendwie ein widerspruch zu sein.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Überschreiben von virtual static Methoden

Beitrag von theo »

Dein Testprogramm kompiliert hier nicht:
Projekt kompilieren, Ziel: /home/theo/lazarus/fpcupdeluxe/projects/project1: Exit code 1, Fehler: 2
project1.lpr(10,53) Error: Procedure directive "STATIC" cannot be used with "VIRTUAL"
project1.lpr(22,54) Error: Procedure directive "STATIC" cannot be used with "VIRTUAL"
Lazarus 2.1.0 r65123M FPC 3.2.0 x86_64-linux-gtk2

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Überschreiben von virtual static Methoden

Beitrag von hubblec4 »

Oh, das ist ja mal interessant.

Ich habe hier noch die Lazarus 2.02 am Start, da kompliert es.

Sieht so aus als ob das in der neusten Version von Lazarus "verboten" ist.

Da wäre es dann wohl besser ich verzichte auf virtaul static Methoden.
Wobei ich das sehr schade finde, denn es würde sich für mein Projekt super anbieten.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Überschreiben von virtual static Methoden

Beitrag von Warf »

Virtual und static zusammen macht ja auch keinen sinn. Static ist ja genau dafür da um keine VMT referenzen auflösen zu müssen, während virtual VMT referenzen benötigt.

Wenn du virtuelle class Methoden benutzen willst, kannst du aber auch einfach das static weglassen:

Code: Alles auswählen

TBase = class
  class procedure foo; virtual;
end;

TChild = class(TBase)
  class procedure foo; override;
end;

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Überschreiben von virtual static Methoden

Beitrag von hubblec4 »

Ok, wenn ich static weg lasse dann kann ich es in Lazaruas 2.0.12 compilieren aber dennoch wird nicht die überschriebene Function verwendet wenn sie nicht direkt aufgerufen wird.

EDIT:
Wenn ich auch noch das static von der Funktion "GetValueOfStaticFunction" entferne dann gehts.
Das ergebnis bei dem Test ist dann immer TRUE.

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Überschreiben von virtual static Methoden

Beitrag von hubblec4 »

Code: Alles auswählen

TBase                  = class
  public
   class function StaticFunction: Boolean; virtual;
   class function GetValueOfStaticFunction: Boolean;

   function NormalFunction: Boolean; virtual;
   function GetValueOfNormalFunction: Boolean;

   class property Value: Boolean read GetValueOfStaticFunction;
 end;  
 
Jetzt kann man aber eine class methode ohne static nicht mehr an eine class property binden.
Da kommt dann folgender Fehler: Error: Illegal symbol for property access.

Ich merke schon das wird wohl so nix und ich muss dann "normale" Methoden verwenden.

Hatte aber gehofft dies zu vermeiden.

Antworten