Delphi: Überschriebene virtuellen Konstruktor Nachkomme nicht durch Überlastung genannt werden
-
28-09-2019 - |
Frage
Noch eine weitere in meiner Reihe von Fragen in Bezug auf Konstrukteuren in Delphi.
Ich habe eine Basisklasse, die den virtuellen Konstruktor hat:
TComputer = class(TObject)
public
constructor Create(Teapot: Integer); virtual;
end;
Der Konstruktor ist virtuell für die Zeiten, dass jemand Bedürfnisse nennen
var
computerClass: class of TComputer;
computer: TComputer;
begin
computer := computerClass.Create(nTeapot);
Der Konstruktor ist overridden
in Nachkommen:
TCellPhone = class(TComputer)
public
constructor Create(Teapot: Integer); override;
end;
TiPhone = class(TCellPhone )
public
constructor Create(Teapot: Integer); override;
end;
Wo TCellPhone
und TiPhone
Nachkommen haben jeweils ihre Möglichkeit, ihre eigene Initialisierung zu tun (die Mitglieder nicht zur besseren Lesbarkeit enthält).
Aber ich nun einen überladenen Konstruktor einige Vorfahren hinzufügen:
TCellPhone = class(TComputer)
public
constructor Create(Teapot: Integer); override; overload;
constructor Create(Teapot: Integer; Handle: string); overload;
end;
Der alternative Konstruktor in TCellPhone ruft die andere virtuelle Konstruktor, so ist es immer das richtige Verhalten außer Kraft gesetzt wird:
constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
TCellPhone.Create(Teapot); //call sibling virtual constructor
FHandle := Handle;
end;
Das Problem ist, dass der Nachkomme, außer Kraft gesetzt, Konstruktor wird nie aufgerufen. Die tatsächliche Stack-Trace-Kette von Anrufen ist:
phone := TiPhone.Create(37, 'spout')
constructor TCellPhone.Create(Teapot: Integer; Handle: string)
constructor TCellPhone.Create(Teapot: Integer)
constructor TComputer.Create(Teapot: Integer)
TObject.Create
Die Geschwister Aufruf TCellPhone.Create(int)
, die virtuell ist, sollte der Nachkomme, außer Kraft gesetzt, die Methode in TiPhone
genannt:
phone := TiPhone.Create(37, 'spout')
constructor TCellPhone.Create(Teapot: Integer; Handle: string)
constructor TiPhone.Create(Teapot: Integer)
constructor TCellPhone.Create(Teapot: Integer)
constructor TComputer.Create(Teapot: Integer)
TObject.Create
So scheint es, dass Versuche, einen Geschwister virtuellen Konstruktor zu verwenden, ist Delphi nicht funktionieren wie erwartet.
Ist es dann eine schlechte Idee für einen Konstruktor anderen zu bedienen? Ist das Design Absicht, dass Code in ladenen Konstruktoren sein copy-paste Versionen voneinander?
ich merke in .NET, dass einige Konstrukteure miteinander verketten:
public Bitmap(int width, int height) : this(width, height, PixelFormat.Format32bppArgb) {}
public Bitmap(int width, int height, PixelFormat format) {...}
Dies scheint nur ein Problem zu sein, wenn:
- ein Konstruktor ist virtuell
- überlasten Sie den Konstrukteuren
Ist die Regel, dass man nicht einen Konstruktor eine andere Überlastung haben kann?
Lösung
Errr ..
constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
TCellPhone.Create(Teapot); //call sibling virtual constructor
FHandle := Handle;
end;
Das sollte sein:
constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
Create(Teapot); //call sibling virtual constructor
FHandle := Handle;
end;
Sie haben gerade eine neue TCellphone Instanz und nicht die andere Methode erstellen aufrufen.