Question

Encore une autre dans ma série de questions concernant les constructeurs à Delphes.

i une classe de base qui a a le constructeur virtuel:

TComputer = class(TObject)
public
    constructor Create(Teapot: Integer); virtual;
end;

Le constructeur est virtuel pour les temps que les besoins de quelqu'un d'appeler

var
   computerClass: class of TComputer;
   computer: TComputer;
begin     
   computer := computerClass.Create(nTeapot);

Le constructeur est overridden dans les descendances:

TCellPhone = class(TComputer) 
public
   constructor Create(Teapot: Integer); override;
end;

TiPhone = class(TCellPhone ) 
public
   constructor Create(Teapot: Integer); override;
end;

Où descendants de TCellPhone et TiPhone ont chacun leur possibilité de faire leur propre initialisation (des membres non inclus pour une meilleure lisibilité).

Mais maintenant j'ajouter un constructeur surchargé d'un ancêtre:

TCellPhone = class(TComputer) 
public
   constructor Create(Teapot: Integer); override; overload;
   constructor Create(Teapot: Integer; Handle: string); overload;
end;

Le constructeur alternatif dans TCellPhone appelle l'autre virtuel constructeur , il obtient toujours le bon comportement surchargée:

constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
   TCellPhone.Create(Teapot); //call sibling virtual constructor

   FHandle := Handle;
end;

Le problème est que le descendant, substituée, le constructeur est jamais appelé. La chaîne de trace de pile réelle d'appels est la suivante:

phone := TiPhone.Create(37, 'spout')
   constructor TCellPhone.Create(Teapot: Integer; Handle: string)
      constructor TCellPhone.Create(Teapot: Integer)
         constructor TComputer.Create(Teapot: Integer)
            TObject.Create

L'appel de frères et soeurs à TCellPhone.Create(int), ce qui est virtuel, aurait dû appeler le descendant, surchargées, à méthode TiPhone:

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

Il semble donc que les tentatives d'utiliser un constructeur virtuel entre frères et soeurs Delphi ne fonctionnent pas comme prévu.

Est-ce donc une mauvaise idée pour un constructeur d'utiliser une autre? L'intention est de conception que le code dans les constructeurs surchargées être copier-coller versions de l'autre?

i remarque dans .NET que certains constructeurs enchaînent les unes aux autres:

public Bitmap(int width, int height) : this(width, height, PixelFormat.Format32bppArgb) {}

public Bitmap(int width, int height, PixelFormat format) {...}

Cela ne semble être un problème si:

  • un constructeur est virtuel
  • vous surchargez les constructeurs

La règle est que vous ne pouvez pas avoir un constructeur surcharge une autre?

Était-ce utile?

La solution

Errr ..

constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
   TCellPhone.Create(Teapot); //call sibling virtual constructor

   FHandle := Handle;
end;

Cela devrait être:

constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
   Create(Teapot); //call sibling virtual constructor

   FHandle := Handle;
end;

Vous venez de créer une nouvelle instance de TCellphone et ne pas appeler l'autre méthode Create.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top