当前位置:主页>销售管理软件> 列表

有点难度:TForm被子继承三次以后,参数就丢了? 两次就

销售管理软件版1楼: 以下是摘录的三个窗口定义的主要部分,内容特简单,请不要怕难读,一晃就明白了~~


//------------------(1)定义FormP
type
TFormP = class(TForm)
public
Para1:String; //可以接受1个参数


constructor TFormP.create(var P1);
begin
inherited Create(Application);
Para1:=P1;
showmessage(''TFormP.create p1=''+para1); //测试用
end;








//------------------(2)定义:继承一次FormP
type
TForm_CXALL = class(TFormP)


procedure TForm_CXALL.FormCreate(Sender: TObject);
begin
// inherited;
showmessage(''TForm_CXALL.FormCreate p1=''+self.Para1); //测试用
end;









//------------------(3)再继承一次FormP,即继承TForm_CXALL
type
TForm_CX_DD = class(TForm_CXALL)


procedure TForm_CX_DD.FormCreate(Sender: TObject);
begin
// inherited;
showmessage(''TForm_CX_DD.FormCreate p1=''+para1);

end;








//(4) 运行TForm_CX_DD的实例
with TForm_CX_DD.create(''ABCD'') do
try
ShowModal
finally
Free;
end;


结果为:
TFormP.create p1=ABCD
TForm_CXALL.FormCreate p1=
TForm_CX_DD.FormCreate p1=

也就是说,参数值在实例中不见了!!!

但是,如果直接运行TForm_CXALL的实例,也就是少继承一次,结果就正确。很奇怪的问题,还请各位诊断一下!

2楼: 在Delphi里面,父类和子类的数据是单独的拷贝,但是方法是公用的,


把你的例子修改了一下,看看和你说的是不是一样的,楼主的问题可能还在于Form的构造函数那里,如果我把TClassA 的Create后面的参数去掉,而在构造函数里面直接设置Name 为ClassA,那么结果就会全部都是ClassA,而现在下面的代码就是楼主的效果

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TClassA = class
public
Name : string;
function GetName:string;virtual;
constructor Create(Value : string);
end;

TClassB = class(TClassA)
public
function GetName:string; override;
constructor Create(Value : string);
end;

TClassC = class(TClassB)
public
function GetName:string;override;
constructor Create(Value : string);
end;

TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
ClassA : TClassA;
ClassB : TClassB;
ClassC : TClassC;
public
{ Public declarations }
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
memo1.Lines.Add(ClassB.Name);
end;

{ TClassA }

constructor TClassA.Create(Value : string);
begin
Name := Value;
end;

function TClassA.GetName: string;
begin
Result := Name;
end;

{ TClassB }

constructor TClassB.Create(Value: string);
begin


end;

function TClassB.GetName: string;
begin
Result := Name;
end;

{ TClassC }

constructor TClassC.Create(Value: string);
begin


end;

function TClassC.GetName: string;
begin
Result := Name;
end;

constructor TForm1.Create(AOwner: TComponent);
begin
inherited;
ClassA := TClassA.Create(''ClassA'');
ClassB := TClassB.Create('''');
ClassC := TClassC.Create('''');
end;

destructor TForm1.Destroy;
begin
ClassA.Free;
ClassB.Free;
ClassC.Free;
inherited;
end;

end.财务软件哪个好

3楼: 我是这样的
TForm1=Class(TForm);
protected
FUserID: String;
public
constructor Create(AOwner: TComponent; AUserID: String; );overload;
end;

constructor TForm1.Create(AOwner: TComponent; AUserID: String; );
begin
FUserID:=AUserID;
inherited Create(AOwner);
end;

....
TForm2=Class(TForm1);

继承多少次也没有问题

4楼: overload是重载,override才是覆盖,而且因为参数不同,所以应该使用reintroduce

5楼: 谢谢二位的回答。
在FormP里我也是用的reintroduce 。
其实,当TForm_CX_DD的实例运行到可见后(摆在界面上),也是可以抓出para1的值是ABCD的,但我希望在FormCreate中,依据参数的不同对窗口做一些初始化工作,但是在FormCreate中却取不到那个值。只有在窗口全部都准备好了之后,比如摆在界面上了才可以取到。然而,如果没有三次继承,比如只有两次时,比如直接运行TForm_CXALL的实例,又是可以取到的。问题就在这里,为什么二可三不可? 注意,强调的是要求在FormCreate中取到传入参数值,而不是其它事件里!
  之前的这种初始化处理一直是放在OnShow中的,可是系统完成后,发现这种做法有些不妥,fsMDIChild型的窗口在OnSHow中也取不到参数值,再强制执行一次OnShow就取到了,总感觉这样做很别扭,不够正统,于是尝试改在FormCreate中。继承两次时成功了,还高兴了一阵子,随知道三次时就成了这副样子呢。

6楼: unit Unit1;



interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Para1:String;

constructor Create(var P1); reintroduce; //overload;
end;

tform2 = class(tform1)
public
procedure FormCreate(Sender: TObject);
constructor Create(var P1); //overload;
end;

TForm3 = class(TForm2)
public
procedure FormCreate(Sender: TObject);
constructor Create(var P1); //overload;
end;

var
Form1,formt: TForm1;
Form2: TForm2;
Form3: TForm3;

implementation

{$R *.dfm}

{ TForm1 }

constructor TForm1.Create(var P1);
begin
inherited Create(Application);
Para1:=string(P1);
showmessage(''TForm1.create p1=''+para1); //测试用

end;

procedure TForm1.Button1Click(Sender: TObject);
var
s:string;
begin
s := ''abcd'';
Form3 := TForm3.Create(s);
form3.ShowModal ;

end;

{ tform2 }

constructor tform2.Create(var P1);
begin
inherited create(P1);
self.OnCreate := FormCreate; ///!!!
showmessage(''TForm2.Create p1=''+self.Para1); ///!!!
end;

procedure tform2.FormCreate(Sender: TObject);
begin
showmessage(''TForm2.FormCreate p1=''+self.Para1); ///在Form3中无用,知道为什么吗

end;

{ TForm3 }

constructor TForm3.Create(var P1);
begin
inherited create(P1);
self.OnCreate := FormCreate;
//放在此处也可以//showmessage(''TForm3.Create p1=''+self.Para1);
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
showmessage(''TForm3.FormCreate p1=''+self.Para1);
end;

end.

销售管理软件版7楼: 楼主把FormCreate 换成 Create 看看

TFormP = class(TForm)


……
constructor Create(AOwner: TComponent; P1: string); reintroduce;
destructor Destoy; override;

TFormP.Create(……)
begin
inherited Create(AOwner);
……
end;

8楼: 我加了 self.OnCreate := FormCreate; ///!!!
还是取不到。谢谢大家,不用再为这事费时间了,大不了就是执行两次FormShow,我在FormP中加个变量ShowOnce做控制算了。

9楼: Create的参数请不要减少。
需要多个创建方式的话用overload吧。

inherited 句使用希望继承的父类的Create方法,参数写全了。

你的inherited 被注释掉了,怎么通知父类啊。
一个变量甚至可以通过层层传送到达父类的私有成员。

*************************************
一句话:
inherited 代表的正是继承关系。你去掉了inherited ,就丢掉了血统,割裂了继承。

10楼: 回 魏启明 :开始时是加上去的,因为不管用,所以就注释掉了。
我估计,也许是 craete 和 formCreate 这两个我没弄清它们之间的关系,有那位能解释一下吗?

11楼: 不关formCreate的事,就Create
formCreate是Application的方法。

constructor标志构造器
destructor标志析构器

12楼: 怀疑lz的说法,根据我的实验,不管继承三次还是两次 OnCreate中是无法得到Para的值的。主要原因是OnCreate在Para赋值之前已经被调用了。OnCreate什么时候被调用请参照VCL源代码。实验代码如下:


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit4, Unit3;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
Form4: TForm4;
begin
Form4 := TForm4.Create(''ABCD'');
try
Form4.ShowModal;
finally
Form4.Free;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
Form3: TForm3;
begin
Form3 := TForm3.Create(''ABCD'');
try
Form3.ShowModal;
finally
Form3.Free;
end;
end;

end.

unit Unit2;

interface



uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
TForm2 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Para : String;
constructor Create(Str : String);reintroduce;
end;

var
Form2: TForm2;

implementation

uses Unit1;

{$R *.dfm}

{ TForm2 }

constructor TForm2.Create(Str: String);
begin
Form1.Memo1.Lines.Add(''TForm2.Create Called before! Para = '' + Para);
inherited Create(Application);
Form1.Memo1.Lines.Add(''TForm2.Create Called before assign value and after create! Para = '' + Para);
Para := Str;
Form1.Memo1.Lines.Add(''TForm2.Create Called after! Para = '' + Para);
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
Form1.Memo1.Lines.Add(''TForm2.FormCreate Called! Para = '' + Para);
end;

end.


unit Unit3;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit2;

type
TForm3 = class(TForm2)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
constructor Create(Str : String);
end;

var
Form3: TForm3;

implementation

uses Unit1;

{$R *.dfm}

constructor TForm3.Create(Str: String);
begin
Form1.Memo1.Lines.Add(''TForm3.Create Called before! Para = '' + Para);
inherited;
Form1.Memo1.Lines.Add(''TForm3.FormCreate Called after! Para = '' + Para);
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
//inherited;
Form1.Memo1.Lines.Add(''TForm3.FormCreate Called! Para = '' + Para);
end;

end.

unit Unit4;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit3;

type
TForm4 = class(TForm3)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
constructor Create(Str : String);
end;

var
Form4: TForm4;

implementation

uses Unit1;

{$R *.dfm}

constructor TForm4.Create(Str: String);
begin
Form1.Memo1.Lines.Add(''TForm4.Create Called before! Para = '' + Para);
inherited;
Form1.Memo1.Lines.Add(''TForm4.FormCreate Called after! Para = '' + Para);
end;

procedure TForm4.FormCreate(Sender: TObject);
begin
//inherited;
Form1.Memo1.Lines.Add(''TForm4.FormCreate Called! Para = '' + Para);
end;

end.


实验结果为:
三次继承时:
TForm4.Create Called before! Para =
TForm3.Create Called before! Para =
TForm2.Create Called before! Para =
TForm4.FormCreate Called! Para =
TForm2.Create Called before assign value and after create! Para =
TForm2.Create Called after! Para = ABCD


TForm3.FormCreate Called after! Para = ABCD
TForm4.FormCreate Called after! Para = ABCD

两次继承时,结果为:
TForm3.Create Called before! Para =
TForm2.Create Called before! Para =
TForm3.FormCreate Called! Para =
TForm2.Create Called before assign value and after create! Para =
TForm2.Create Called after! Para = ABCD
TForm3.FormCreate Called after! Para = ABCD免费库存软件下载

13楼: 此问题的解决办法可以使 Supermay 兄 提到的
将赋值放在 inherited之前解决

销售管理软件版14楼: 如下已经没什么问题 "强调的是要求在FormCreate中取到传入参数值,而不是其它事件里"
但我怀疑用inherited从在FormCreate中取到传入参数值的用处
////////project2.dpr
program Project2;

uses
Forms,
Main in ''Main.pas'' {frmMain},
uform1 in ''uform1.pas'' {Form1};

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TfrmMain, frmMain);


Application.Run;
end.

///////main.pas
unit Main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,
uform1;

type
TfrmMain = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmMain: TfrmMain;
Form3: TForm3;

implementation

{$R *.dfm}

procedure TfrmMain.Button1Click(Sender: TObject);
var
s:string;
begin
s := ''ABCD'';
Form3 := TForm3.Create(s);
form3.ShowModal ;
form3.Free;
end;

end.

////main.dfm
object frmMain: TfrmMain
Left = 192
Top = 114
Width = 696
Height = 480
Caption = ''frmMain''
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = ''MS Sans Serif''
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 232
Top = 80
Width = 32
Height = 13
Caption = ''Label1''
end
object Button1: TButton
Left = 288
Top = 176
Width = 75
Height = 25
Caption = ''Button1''
TabOrder = 0
OnClick = Button1Click
end
end


//////uform1.pas
unit uform1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Label1: TLabel;
Button1: TButton;
private
{ Private declarations }
public
{ Public declarations }
Para1:String;

constructor Create(var P1); overload;
end;

tform2 = class(tform1)
public
procedure FormCreate(Sender: TObject); //reintroduce; overload;
constructor Create(var P1);
end;

TForm3 = class(TForm2)
public
procedure FormCreate(Sender: TObject);
constructor Create(var P1);
end;


implementation

{$R *.dfm}

constructor TForm1.Create(var P1);
begin
inherited Create(Application);

Para1:=string(P1);
showmessage(''TForm1.create p1=''+para1); //测试用
end;

{tform2}

constructor tform2.Create(var P1);
begin
inherited create(P1);
self.OnCreate := FormCreate;
end;

procedure tform2.FormCreate(Sender: TObject);
begin
inherited;
showmessage(''TForm2.FormCreate p1=''+self.Para1);
end;

{ TForm3 }

constructor TForm3.Create(var P1);
begin
inherited create(P1);
self.OnCreate := FormCreate;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
inherited;
showmessage(''TForm3.FormCreate p1=''+self.Para1);
end;

end.

//////uform1.dfm
object Form1: TForm1
Left = 192
Top = 149
Width = 606
Height = 250
Caption = ''Form1''
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = ''MS Sans Serif''
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 200
Top = 40
Width = 32
Height = 13
Caption = ''Label1''
end
object Button1: TButton
Left = 304
Top = 48
Width = 75
Height = 25
Caption = ''Button1''
TabOrder = 0
end
end

15楼: 按照OO原则的推荐
在构造时首先调用inherited
在析构时最后调用inherited

但这只是为了防止其他的代码执行到未生成或已释放的资源。

这里的只是个字符串参数,没问题的。
当然没有特别的原因最好按规则办事。

遵从规则-->理解规则-->超越规则

16楼: 不要再用application的FormCreate生成Form
它调用默认的构造函数。

17楼: 多人接受答案了。