Delphi / pascal: перегрузка конструктора другим прототипом - PullRequest
19 голосов
/ 18 ноября 2009

Я пытаюсь создать дочерний класс TForm с

  1. специальный конструктор для определенных случаев, а
  2. конструктор по умолчанию, который будет поддерживать совместимость с текущим кодом.

У меня сейчас такой код:

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): объявление« Создать »отличается от предыдущего объявления».
  • превращение второго конструктора в функцию класса компилируется без каких-либо ошибок или предупреждений, но умирает с нарушением доступа во время выполнения (все члены-члены равны нулю).

Ответы [ 3 ]

30 голосов
/ 19 ноября 2009

Есть действительно простой способ избежать этого. Дайте вашему новому конструктору другое имя. В отличие от некоторых других популярных языков, Delphi имеет именованных конструкторов ; вам не нужно называть их «Создать». Вы можете вызвать ваш новый CreateWithDataset и вообще не мешать виртуальному конструктору Create.

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)
  /// additional constructor allows for a caller-defined base data set
  constructor Create(AOwner: TComponent; ADataSet: TDataSet; ACaption: string = ''); reintroduce;
end;

Попытка вызова конструктора с одним аргументом непосредственно в TfrmEndoscopistSearch приведет к ошибке компиляции.


(Создание его полиморфно обычно включает использование Application.CreateForm:

Application.CreateForm(TfrmEndoscopistSearch, frmEndoscopistSearch);

Это всегда вызывает виртуальный конструктор с одним аргументом, представленный в TComponent. Если это не ваша основная форма, вам не нужно это делать. Я уже писал о своих чувствах на Application.CreateForm раньше.)

19 голосов
/ 18 ноября 2009

Попробуйте добавить reintroduce перед вторым overload, например:

  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;

Это компилируется в Turbo Delphi. Мне нужно было public сделать его компиляцией, потому что перегрузка published методов ограничена.

6 голосов
/ 15 ноября 2012
constructor Create(AOwner:Tcomponent;str:string);overload;
... 
constructor TfrmEndoscopistSearch.Create(AOwner: Tcomponent; str: string);
    begin
    inherited Create(AOwner);
    showmessage(str);
    end;

Это должно сработать

...