2014-10-01 77 views
2

我想要一个从具有自定义构造函数的BaseForm派生的MainForm。由于这是Mainform,因此通过在* .dpr文件中调用Application.CreateForm(TMyMainForm,MyMainForm)来创建它。但是,我的自定义构造函数在窗体创建过程中未被调用。以自定义构造函数作为mainform的Delphi窗体?

很明显,它工作正常,如果我打电话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; 

回答

8

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

要做你正在尝试的,不要使用reintroduce你的构造函数。创建您的基本形式单独构造,然后让你的MainForm override标准的构造函数来调用定制基构造函数,如:

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; 
+1

大多数时候,所有人都试图通过这种方法来做的是通过构造函数初始化派生类中的成员。我不推荐这个。相反,您也可以在派生表单创建后定义公共属性并对它们进行初始化。这是额外的一两行代码,但是又如何? – 2014-10-01 06:26:09

+2

带参数的构造函数的优点是你**必须传递一些东西,所以你不能忘记传递所需的设置。设置属性可以被遗忘。这不是因为人们想要节省输入几行,而只是因为它是更好的策略,IMO。 – 2014-10-01 07:32:03

+0

这个计划的原因正是由Rudy指出的,@RudyVelthuis我的意图是拥有一个共同的基本形式,它具有背景,处理NCHitTest,记住最后的位置,大小等(从注册表中读取/写入)并导出所有未来的项目从那。有没有比上述策略更好的方法? – ss2006 2014-10-01 09:03:14

1

为了使表成为VCL主要形式,它必须创建通过致电Application.CreateForm。这又调用TComponent中声明的虚拟构造函数。所以,没有办法得到一个不同的构造函数来调用VCL主表单。

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

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

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

在您的派生类中,您将覆盖这些抽象方法。不用在构造函数中设置属性,基本窗体类中的代码就可以调用这些方法。当然,如果你需要在构造函数中工作,你可以完美地从构造函数中调用这些方法。

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

相关问题