Delphi:重载的虚拟构造函数后代未被重载调用

Ian*_*oyd 1 delphi constructor delphi-5 constructor-chaining

关于Delphi中构造函数的一系列问题还有另一个问题.

我有一个具有虚拟构造函数的基类:

TComputer = class(TObject)
public
    constructor Create(Teapot: Integer); virtual;
end;
Run Code Online (Sandbox Code Playgroud)

构造函数是虚拟的,适合有人需要调用的时间

var
   computerClass: class of TComputer;
   computer: TComputer;
begin     
   computer := computerClass.Create(nTeapot);
Run Code Online (Sandbox Code Playgroud)

构造函数overridden位于后代:

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

TiPhone = class(TCellPhone ) 
public
   constructor Create(Teapot: Integer); override;
end;
Run Code Online (Sandbox Code Playgroud)

哪里TCellPhoneTiPhone后代都有机会进行自己的初始化(为了便于阅读而不包括成员).

但是现在我向一些祖先添加了一个重载的构造函数:

TCellPhone = class(TComputer) 
public
   constructor Create(Teapot: Integer); override; overload;
   constructor Create(Teapot: Integer; Handle: string); overload;
end;
Run Code Online (Sandbox Code Playgroud)

TCellPhone中的备用构造函数调用另一个虚拟构造函数,因此它始终获得正确的重写行为:

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

   FHandle := Handle;
end;
Run Code Online (Sandbox Code Playgroud)

问题是永远不会调用后代,重写的构造函数.实际的堆栈跟踪调用链是:

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

兄弟的调用TCellPhone.Create(int),它是虚拟的,应该调用后代,被覆盖的方法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
Run Code Online (Sandbox Code Playgroud)

所以似乎尝试使用兄弟虚拟构造函数是Delphi不能按预期工作.

那么一个构造函数使用另一个构造函数是一个坏主意吗?设计意图是重载构造函数中的代码是彼此的复制粘贴版本吗?

我在.NET中注意到一些构造函数相互链接:

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

public Bitmap(int width, int height, PixelFormat format) {...}
Run Code Online (Sandbox Code Playgroud)

这似乎只是一个问题,如果:

  • 构造函数是虚拟的
  • 你重载构造函数

规则是你不能让一个构造函数重载另一个吗?

The*_*Fox 8

Errr ..

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

   FHandle := Handle;
end;
Run Code Online (Sandbox Code Playgroud)

那应该是:

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

   FHandle := Handle;
end;
Run Code Online (Sandbox Code Playgroud)

您只是创建一个新的TCellphone实例而不是调用另一个Create方法.