2

我想要一个从具有自定义构造函数的 BaseForm 派生的 MainForm。由于这是 Mainform,它是通过调用*.dpr 文件中的Application.CreateForm(TMyMainForm, MyMainForm)创建的。但是,在表单创建期间不会调用我的自定义构造函数。

显然,如果我调用MyMainForm := TMyMainForm.Create(AOwner) ,它工作正常。我可以不使用带有自定义构造函数的表单作为主表单吗?

TBaseForm = class(TForm)
  constructor Create(AOwner:TComponent; AName:string);reintroduce;
end;

TMyMainForm = class(TBaseForm)
  constructor Create(AOwner:TComponent);reintroduce;
end;  

constructor TBaseForm.Create(AOwner:TComponent);

begin;
  inherited Create(AOwner);
end;

constructor TMyMainForm.Create(AOwner:TComponent);

begin;
  inherited Create(AOwner, 'Custom Constructor Parameter');
end;  
4

2 回答 2

8

Application.CreateForm()不能调用reintroduce'd 构造函数。创建新对象时,它调用TComponent.Create()构造函数并期望多态调用任何派生构造函数。通过reintroduce'ing 你的自定义构造函数,你不是多态调用链的一部分。reintroduce公开了一个全新的方法,它与继承的方法具有相同的名称,但与之无关。

要执行您正在尝试的操作,请不要reintroduce用于您的构造函数。在 Base 表单中创建一个单独的构造函数,然后将 MainFormoverride作为标准构造函数并调用您的自定义 Base 构造函数,例如:

TBaseForm = class(TForm)
  constructor CreateWithName(AOwner: TComponent; AName: string); // <-- no reintroduce needed since it is a new name
end;

TMyMainForm = class(TBaseForm)
  constructor Create(AOwner: TComponent); override; // <-- not reintroduce
end;  

constructor TBaseForm.CreateWithName(AOwner: TComponent; AName: string);
begin;
  inherited Create(AOwner);
  // use AName as needed...
end;

constructor TMyMainForm.Create(AOwner: TComponent);
begin;
  inherited CreateWithName(AOwner, 'Custom Constructor Parameter');
end;  
于 2014-10-01T02:30:40.160 回答
2

为了使表单成为 VCL 主表单,必须通过调用Application.CreateForm. 这反过来又调用在 中声明的虚拟构造函数TComponent。因此,无法为 VCL 主窗体调用不同的构造函数。

一种选择是雷米提出的。覆盖在 中声明的构造函数TComponent,并调用不同的构造函数传递额外的参数。这可以是同一类中的构造函数,也可以是从基类继承的构造函数。

这里的另一个选择是在基类上使用抽象类方法。例如,

type
  TMainFormBase = class(TForm)
  protected
    class function ProjectName: string; virtual; abstract;
    class function RegKeyPath: string; virtual; abstract;
  end;

在您的派生类中,您将覆盖这些抽象方法。而不是在构造函数中设置属性,基表单类中的代码可以只调用这些方法。当然,如果你需要在构造函数中工作,你完全可以从构造函数中调用这些方法。

就个人而言,我对向已经具有虚拟构造函数的类添加新构造函数有偏见。虚拟构造函数范式引导您使用单个虚拟构造函数,仅此而已。如果您开始在层次结构的下方添加不同的构造函数,那么在虚拟实例化时很容易因调用错误的构造函数而导致麻烦。

于 2014-10-02T10:01:31.257 回答