![]() |
Warum virtual / override bei destructor / constructor?
Hallo! Ich möchte endlich mal verstehen, warum es so ist. In der Unit System wird TObject eingeführt und der Constructor ohne "virtual", aber der Destructor mit "virtual" deklariert.
Entsprechend muss man bei der Ableitung beim Destructor das Schlüsselwort "override" angeben, während man beim Constructor einfach so Create() überschreiben kann. In beiden Routinen kann und soll man dann mit "inherited" die Vorfahrroutine aufrufen. WARUM bloß ist das so? Warum ist bei Create kein "virtual" deklariert und es geht trotzdem alles und warum braucht man beim Destructor das "virtual > override"? Hätten die Entwickler von TObject nicht beide Prozeduren analog deklarieren können? Also beide mit oder beide ohne "virtual"? Gibt es einen Grund, warum es so ist? Mich irritiert es schon immer, dass ich bei Create ohne override auskomme, bei Destroy es aber angeben muss, sich aber beide Prozeduren ansonsten identisch zu verhalten scheinen, abgeleitet und überschrieben werden können und "inherited" auch verwendbar ist. Danke im voraus für jede Erhellung des Sachverhalts!
Delphi-Quellcode:
und die Verwendung in abgeleiteten Klassen:
{ unit System }
TObject = class public constructor Create; { ...} protected destructor Destroy; virtual; {... } constructor TObject.Create; begin end; destructor TObject.Destroy; begin end;
Delphi-Quellcode:
TMyObject = class(TObject)
constructor Create; destructor Destroy; override; { ...} implementation constructor TObject.Create; begin inherited; { ... } end; destructor TObject.Destroy; begin { ... } inherited; end; |
AW: Warum virtual / override bei destructor / constructor?
Delphi-Quellcode:
var
AObj: TObject; begin AObj := TMyObj.Create; // hier gibst du eh konkret an, ob ein TMyObj oder ein TObject oder sonstwas erstellt werden soll, auch wenn die Variable als TObject deklariert ist ... AObj.Destroy; // bzw. Free; // ohne das virtual würde hier der Destructor von TObject aufgerufen, mit virtual wird korrekterweise der von TMyObj aufgerufen end; |
AW: Warum virtual / override bei destructor / constructor?
Danke für die schnelle Antwort. Aber warum funktioniert das Ableiten von Create auch ohne "virtual"? Das Konzept, warum "virtual" mal nötig und mal nicht nötig ist, leuchtet mir nicht ein.
Warum ruft "inherited" trotzdem die richtige Vorfahrroutine auf und ist verwendbar? Ich hätte eigentlich gedacht, dass man "virtual" deklarieren muss, wenn man möchte, dass die Klasse überschrieben werden kann? Es ist ja nicht einmal ein "reintroduce" nötig, man kann einfach Create neu definieren ohne Probleme... |
AW: Warum virtual / override bei destructor / constructor?
Das inherited hat damit nicht direkt was zu tun. Damit sagst du nur, ob und an welcher Stelle die Methode des Vorfahren aufgerufen wird, was man in der Regel will, um nicht alles neu implementieren zu müssen bzw. bei Änderungen alle Nachfahren anfassen zu müssen.
Das Virtual bedeutet nur, dass das Programm zur Laufzeit prüft ob es in obigem Beispiel wirklich ein TObject (so ist die Variable deklariert) oder ein Nachfahre davon ist. Ist es ein Nachfahre wird dessen Destructor aufgerufen. Ohne das Virtual würde in diesem Fall TObject.Destroy aufgerufen, was ja falsch wäre. |
AW: Warum virtual / override bei destructor / constructor?
Virtual bei
Delphi-Quellcode:
benötigt man z.b. in folgendem Falle:
Create
Delphi-Quellcode:
Hätte man den Constructor hier nicht als
type
TBaseClass = class(TObject) public constructor Create; virtual; end; TClassA = class(TBaseClass) public constructor Create; override; end; TClassB = class(TBaseClass) public constructor Create; override; end; TClassType = class of TBaseClass; .. function DynamicCreate(ClassType: TClassType): TBaseClass; begin Result := ClassType.Create; end;
Delphi-Quellcode:
deklariert, würde immer Der von
virtual
Delphi-Quellcode:
aufgerufen. Mit
TBaseClass
Delphi-Quellcode:
ruft die Funktion korrekt den Constructor der konkreten Klasse auf.
virtual
|
AW: Warum virtual / override bei destructor / constructor?
Das bedeutet dann aber auch, dass die Entwicklung der Unit System problemlos sowohl den Constructor Create als auch den Destructor Destroy hätten analog mit "virtual" deklarieren können und alles funktionieren würde? Ist das so?
Dieses Analogie der Deklarationen würde sicherlich vielen Anfängern Irritationen ersparen. |
AW: Warum virtual / override bei destructor / constructor?
Zitat:
|
AW: Warum virtual / override bei destructor / constructor?
OK, danke.
Warum kann man den "constructor create" überschreiben, ohne "reintroduce" angeben zu müssen? Müsste das nicht kollidieren? Wenn auch ohne "virtual/override" eine Vorfahrprozedur überschrieben und verdeckt werden kann und trotzdem mittels "inherited" die Vorfahrprozedur aufgerufen werden kann, dann verstehe ich eigentlich nicht, wozu man überhaupt "virtual/override" braucht? |
AW: Warum virtual / override bei destructor / constructor?
Was Zacherl gezeigt hat, sieht man zum Beispiel bei TComponent. Dort ist der Konstructor virtual, was benötigt wird, wenn vom Streaming Mechanismus (Form wird aus dfm geladen) die ganzen Komponenten erstellt werden.
Wäre TObject.Create virtual, müsste man jegliche Klasse über TClass erzeugen können, obwohl diese Klasse möglicherweise gar keinen parameterlosen Konstruktor haben soll. Aktuell gibt es nur den kleinen haken, dass ein Create auf einer TClass variable fest TObject.Create aufruft, was weitaus weniger schlimm ist. Zitat:
Mir scheint, da sind noch ein paar Wissenslücken bzgl OOP/Polymorphie verhanden, die das Verständnis etwas erschweren. P.S. Da sieht man mal, warum C# es erforderlich macht, auf jeder Klasse explizit einen Konstruktor zu definieren (selbst wenn er nix macht). Weil implizit einen erben nur verwirrt und zu Defekten führen kann. |
AW: Warum virtual / override bei destructor / constructor?
Zitat:
Zitat:
Der Unterschied ist, ob zur Laufzeit die Methode des echten Typs (ggf. Nachfahren) oder die des Variablentyps aufgerufen wird |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz