Delphi: surchargée descendant constructeur virtuel ne pas être appelé par surcharge
-
28-09-2019 - |
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?
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.