Delphi/pascal:使用不同的原型重载构造函数

Delphi/pascal:使用不同的原型重载构造函数,delphi,constructor,overloading,Delphi,Constructor,Overloading,我正在尝试使用创建TForm的子类 特定情况下的特殊构造函数,以及 将保持与当前代码兼容的默认构造函数 这是我现在拥有的代码: interface TfrmEndoscopistSearch = class(TForm) public /// original constructor kept for compatibility constructor Create(AOwner : TComponent); overload; override; /// add

我正在尝试使用创建TForm的子类

  • 特定情况下的特殊构造函数,以及
  • 将保持与当前代码兼容的默认构造函数
  • 这是我现在拥有的代码:

    interface
      TfrmEndoscopistSearch = class(TForm)
      public
        /// original constructor kept for compatibility
        constructor Create(AOwner : TComponent); overload; override;
        /// additional constructor allows for a caller-defined base data set
        constructor Create(AOwner : TComponent; ADataSet : TDataSet; ACaption : string = ''); overload;
      end;
    
    它似乎有效,但我总是收到编译器警告:

    [Warning] test.pas(44): Method 'Create' hides virtual method of base type 'TCustomForm' [警告]test.pas(44):方法“Create”隐藏基类型“TCustomForm”的虚拟方法
    • 在第二个构造函数之后添加“重载;”将无法编译。“[Error]test.pas(44)“'Create'的声明与以前的声明不同”
    • 使第二个构造函数成为类函数编译时不会出现任何错误或警告,但在运行时会因访问冲突而终止(所有成员变量均为零)

    尝试在第二个
    重载之前添加
    重新引入
    ,如下所示:

      TfrmEndoscopistSearch = class(TForm)
      public
        /// original constructor kept for compatibility
        constructor Create(AOwner : TComponent); overload; override;
        /// additional constructor allows for a caller-defined base data set
        constructor Create(AOwner : TComponent; ADataSet : TDataSet; ACaption : string = ''); reintroduce; overload;
      end;
    
    TfrmEndoscopistSearch = class(TForm)
      /// additional constructor allows for a caller-defined base data set
      constructor Create(AOwner: TComponent; ADataSet: TDataSet; ACaption: string = ''); reintroduce;
    end;
    

    这是用turbodelphi编译的。我需要
    public
    来编译它,因为
    发布的
    方法的重载受到限制。

    有一种非常简单的方法来避免这种情况给你的新构造函数起一个不同的名字。与其他一些流行语言不同,Delphi给构造函数起了名字;你不必叫他们Create。您可以调用新的CreateWithDataset,而完全不干扰虚拟创建构造函数

    TfrmEndoscopistSearch = class(TForm)
      /// original constructor kept for compatibility
      constructor Create(AOwner: TComponent); override;
      /// additional constructor allows for a caller-defined base data set
      constructor CreateWithDataset(AOwner: TComponent; ADataSet: TDataSet; ACaption: string = '');
    end;
    
    事实上,除非您以多态方式实例化这个类,否则您甚至不需要原始构造函数。您可以这样声明您的新版本:

      TfrmEndoscopistSearch = class(TForm)
      public
        /// original constructor kept for compatibility
        constructor Create(AOwner : TComponent); overload; override;
        /// additional constructor allows for a caller-defined base data set
        constructor Create(AOwner : TComponent; ADataSet : TDataSet; ACaption : string = ''); reintroduce; overload;
      end;
    
    TfrmEndoscopistSearch = class(TForm)
      /// additional constructor allows for a caller-defined base data set
      constructor Create(AOwner: TComponent; ADataSet: TDataSet; ACaption: string = ''); reintroduce;
    end;
    
    试图直接在TFRMendoscopitSearch上调用单参数构造函数将产生编译错误


    (以多态方式创建它通常需要使用Application.CreateForm:

    Application.CreateForm(TfrmEndoscopistSearch, frmEndoscopistSearch);
    
    它总是调用TComponent中引入的单参数虚拟构造函数。除非它是您的主要形式,否则您不需要这样做。我以前写过。)


    这应该可以解决问题

    这可能是最合适的解决方案,但它不是问题的答案。练习的一部分是修复问题,而不必更改已经使用一种或另一种形式的create()的其他10个左右的文件中的任何一个。我从两个不同的项目中合并了这个表单,我不想把它分叉。答案是正确的,但可能有点危险。如果第三方用户使用该代码,他可能会(意外地)调用标准构造函数(Create),而不是新的构造函数。我不认为这会被视为“危险的”@Migrate。在我的回答中,我指出保留原始构造函数是为了兼容性。也就是说,这是为了与希望调用原始构造函数的代码兼容。如果这样做是合法的,那么不可能判断这是否是“偶然的”。但是,如果兼容性不是一个问题,那么这个答案中的第二个代码块已经演示了如何防止人们在有限的情况下调用原始构造函数。危险在哪里?班戈!“重新引入”关键字正是我们所需要的。还需要原始构造函数,因为它将数据集设置为正确的默认值。