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?

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top