代码之家  ›  专栏  ›  技术社区  ›  Ian Boyd

Delphi:重载未调用重写的虚拟构造函数子体

  •  1
  • Ian Boyd  · 技术社区  · 14 年前

    还有一个关于Delphi中构造函数的问题。

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

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

    构造函数在需要调用的时间内是虚拟的

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

    构造器是 overridden 在后代中:

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

    在哪里? TCellPhone TiPhone 每个子代都有机会进行自己的初始化(不包括可读性的成员)。

    但现在我将重载构造函数添加到某个祖先:

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

    TCellPhone中的备用构造函数调用另一个 事实上的 构造函数,因此它总是获得正确的重写行为:

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

    问题是,从未调用子体、重写的构造函数。实际的堆栈跟踪调用链是:

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

    兄弟姐妹的呼唤 TCellPhone.Create(int) 电话 :

    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
    

    因此,使用兄弟虚拟构造函数is Delphi的尝试似乎没有按预期工作。

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

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

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

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

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

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

    1 回复  |  直到 14 年前
        1
  •  8
  •   The_Fox    14 年前

    呃。。

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

    应该是:

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

    您只是创建了一个新的TCellphone实例,而没有调用另一个Create方法。