Entwickler-Ecke
Sonstiges (Delphi) - Lazarus Vererbung virtual abstract override
glotzer - So 23.06.13 11:13
Titel: Lazarus Vererbung virtual abstract override
Hallo,
Ich hab ein Problem mit der Vererbung in Lazarus,
ich bin jetzt seit 2 Tagen am rumprobieren und finde einfach keine Lösung.
Google kann mir leider auch nicht helfen (wahrscheinlich verwende ich die falschen Suchbegriffe)
Mein Problem ist eigentlich sehr einfach, ich habe 3 Klassen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| type TA = class public procedure x; virtual; abstract; end;
TB = class(TA) public procedure x; override; end;
TC = class(TB) public procedure m; end;
D = class of TA; |
Wenn ich jetzt x so aufrufe:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var obj: TA; Objclass: D; begin Objclass := TC; obj := Objclass.Create; obj.x; obj.Free; end; |
kommt der Fehler x sei abstract und nicht implementiert (genauer :
)
Ich kann in der Klasse TB auch keine Haltepunkte setzen, es scheint als würde der Compiler die Klasse ignorieren.
Das abschalten der Optimierung hat auch nicht geholfen.
Ich vermute es liegt irgendwie an der Klassenreferenz...
Vieleicht hat ja hier jemand eine tolle Idee, würd mich freuen :D
Grüße
Glotzer
jaenicke - So 23.06.13 11:47
Ich glaube du meinst eher:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var obj: TA; Objclass: D; begin Objclass := TC; obj := Objclass.Create; obj.x; obj.Free; end; |
glotzer - So 23.06.13 11:49
ups ja, danke.
Allerdings nur hier ein kleiner Tippfehler, im eigentlichen Programm ist es schon richtig.
jaenicke - So 23.06.13 13:50
Dann hast du wohl eine alte Version von Lazarus. In Version 1.0.10 funktioniert das problemlos, genau wie in Delphi.
glotzer - So 23.06.13 13:55
hmm ich verwende 1.0.8.
Danke für deine Mühe ich versuchs mal mit nem Update.
Tranx - So 23.06.13 14:26
Entschuldige, aber Du definierst ja auch obj als TA:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var obj: TA; <=== Objekt hat TA-Klasse Objclass: D; begin Objclass := TC; obj := Objclass.Create; obj.x; obj.Free; end; |
wie wäre es denn, wenn Du das schreibst:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var obj: TC; begin obj := TC.Create; obj.x; obj.Free; end; |
Ich benutze als einer Komponente TStringgrid ja auch nicht TCustomGrid als Klassenzuordnung für die Komponente sondern eben TStringgrid.
Martok - So 23.06.13 14:26
Mich wundert grade etwas, dass das wieder geht :)
Eigentlich war das mal sehr lange so, dass der Konstruktor einer Klasse, die per Klassenreferenz erzeugt wird, virtuell sein muss. Im Beispiel würde sonst immer TA.Create aufgerufen werden, weil die Referenz da hin zeigt.
Übrigens ist Laz 1.1 und FPC 2.7.1 aktuell. Sollte man mal updaten (ggf. auch auf Snapshots). Man kennt das heute gar nicht mehr, aber bei denen wird wirklich aktiv entwickelt, da sind 4 Wochen nicht aktualisiert eine halbe Welt.
glotzer - So 23.06.13 14:42
Hab grad noch keine Zeit gehabt zu Updaten, aber:
Tranx hat folgendes geschrieben : |
wie wäre es denn, wenn Du das schreibst:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| var obj: TC; begin obj := TC.Create; obj.x; obj.Free; end; |
Ich benutze als einer Komponente TStringgrid ja auch nicht TCustomGrid als Klassenzuordnung für die Komponente sondern eben TStringgrid. |
Würd ich ja gerne aber kann ich nicht, sonst könnte ich mir die komplette Nummer mit der Klassenreferenz sparen.
Es geht darum, dass abhängig von einer Usereingabe Objekte verschiedener Klassen erzeugt werden, welche sich vorher Registriert haben. Ich weiß zur Designzeit nur, dass sie alle von der selben Klasse abgeleitet sind.
Martok hat folgendes geschrieben : |
Mich wundert grade etwas, dass das wieder geht :)
Eigentlich war das mal sehr lange so, dass der Konstruktor einer Klasse, die per Klassenreferenz erzeugt wird, virtuell sein muss. Im Beispiel würde sonst immer TA.Create aufgerufen werden, weil die Referenz da hin zeigt. |
Er ist virtuell.
Martok hat folgendes geschrieben : |
Übrigens ist Laz 1.1 und FPC 2.7.1 aktuell. Sollte man mal updaten (ggf. auch auf Snapshots). Man kennt das heute gar nicht mehr, aber bei denen wird wirklich aktiv entwickelt, da sind 4 Wochen nicht aktualisiert eine halbe Welt. |
Wird gemacht, danke.
jaenicke - So 23.06.13 14:46
Martok hat folgendes geschrieben : |
Eigentlich war das mal sehr lange so, dass der Konstruktor einer Klasse, die per Klassenreferenz erzeugt wird, virtuell sein muss. Im Beispiel würde sonst immer TA.Create aufgerufen werden, weil die Referenz da hin zeigt. |
Das ist auch so, aber wenn man z.B. gar keinen Konstruktor in TB hat, ist es ja korrekt, dass der des Vorfahren aufgerufen wird.
Wenn man natürlich einen in der abgeleiteten Klasse definiert, kann man den der Elternklasse nicht überschreiben, wenn der nicht als virtuell definiert ist.
glotzer - So 23.06.13 14:55
Gerade geupdated, keine Änderung, weiterhin das selbe Problem.
Ich versuch mal ein möglichst kleines Testprojekt zu machen.
jaenicke - So 23.06.13 15:30
Ein Testprojekt ist natürlich das beste, aber du kannst auch erstmal die konkreten Deklarationen posten, die du im echten Projekt benutzt, die müssen ja so nicht kompilierbar sein.
glotzer - So 23.06.13 16:47
Ich poste hier jetzt nur das entscheidende, ein komplettes Projekt ist im Anhang, es (sollte) auch kompilierbar sein.
main:
Delphi-Quelltext
1: 2: 3: 4: 5:
| var GUI: TBasicGUI; begin GUI := CreateGUISystem(GUI_Systems.Items[GUISelBox.ItemIndex]); end; |
basicGUI:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47:
| type
TBasicGUI = class(TStringList) public constructor Create; virtual; destructor Destroy; override; end;
type TBasicGUIClass = class of TBasicGUI; TBasicGUIList = specialize TFPGList<TBasicGUIClass>;
var GUI_Systems: TBasicGUIList;
function CreateGUISystem(ASystem: TBasicGUIClass): TBasicGUI; procedure RegisterGUISystem(ASystem: TBasicGUIClass);
implementation
function CreateGUISystem(ASystem: TBasicGUIClass): TBasicGUI; begin result := ASystem.create; end;
procedure RegisterGUISystem(ASystem: TBasicGUIClass); begin GUI_Systems.Add(ASystem); end;
constructor TBasicGUI.Create; begin inherited Create; showmessage('a'); end;
destructor TBasicGUI.Destroy; begin inherited Destroy; end;
initialization GUI_Systems := TBasicGUIList.Create;
finalization GUI_Systems.Free; |
basicguiform:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| type
TBasicFormGUI = class(TBasicGUI) public constructor Create; override; destructor Destroy; override; end;
{$R *.lfm}
implementation
constructor TBasicFormGUI.Create; begin inherited Create; showmessage('b'); end;
destructor TBasicFormGUI.Destroy; begin inherited Destroy; end; |
gui_Tiatai:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| type TTiatai = class(TBasicFormGUI) public a: integer; end;
implementation
initialization RegisterGUISystem(TTiatai); |
Problem ist, dass nur "a" angezeigt wird, niemals "b". Es sollte beides angezeigt werden.
jaenicke - So 23.06.13 18:14
Du hast TBasicFormGUI doppelt deklariert...
Das mit dem Showmessage b aus basicguiform.pas wird nie benutzt, sondern das aus basicformgui.pas.
glotzer - So 23.06.13 18:18
WOW, da muss man erstmal drauf kommen! vielen vielen Dank! Ich wär da wohl noch ewig davor gesessen ^^
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!