为什么子类对象不可以传递给父类的变量?

mylovelypig 2007-03-20 07:15:27
TTest1 = class

end;

TTest2 = class(TTest1)

end;

procedure TestFun(var Test: TTest1);
begin

end;

procedure TForm1.Button1Click(Sender: TObject);
var
Test1: TTest1;
Test2: TTest2;
begin
Test1 := TTest1.Create;
Test2 := TTest2.Create;
Test1 := Test2; //这里可以

TestFun(Test2); //这里编译出错:Types of actual and formal var parameters must be identical

end;
...全文
273 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
lihuasoft 2007-03-21
  • 打赏
  • 举报
回复
(我)哦,你在FormClass.CRMCreate(Application, InitCode);时,使用的是TCRMForm类的构造方/法,而TCRMForm类没有TfrmCustList的Panel1这个成员。
========================================
(楼主)我个人的看法,其实并不象你所说的那样.
OpenForm(TfrmCustList, frmCustList, 'TestCode');
在这个语句后加一条语句检测你就知道,
if Assigned(frmCustList) then
ShowMessage('OK')
else
ShowMessage('NO')


--------------------------------------------

关于这个问题(用Assigned判断),你去看:http://rabbitfox.blog.sohu.com/38595319.html
关于在OpenForm过程里调用的倒底是哪个类的Create方法,有一个简单的做法可以验证:你把鼠标光标移到 FormClass.CRMCreate一句的CRMCreate上去,看一下HINT,显示的是哪个类。
Harryfin 2007-03-21
  • 打赏
  • 举报
回复
不过貌似去掉var后就不需要这样写了 -_-
Harryfin 2007-03-21
  • 打赏
  • 举报
回复
TestFun(Test2);

改成

TestFun(TTest1(Test2));
lihuasoft 2007-03-21
  • 打赏
  • 举报
回复
那就祝贺喽!...不必客气
rtx2006 2007-03-21
  • 打赏
  • 举报
回复
procedure TForm1.Button1Click(Sender: TObject);
var
Test1: TTest1;
Test2: TTest2;
begin
Test1 := TTest1.Create;
Test2 := TTest2.Create;
Test1 := Test2; //这里可以

TestFun(Test2); //这里编译出错:Types of actual and formal var parameters must be identical

end;
好像有内在泄露吧?
chenzhuo 2007-03-21
  • 打赏
  • 举报
回复
procedure OpenForm(FormClass: TCRMFormClass; var FormName; InitCode: string);
begin
TCRMForm(FormName) := FormClass.CRMCreate(Application, InitCode);
TCRMForm(FormName).Show;
// others
end;
mylovelypig 2007-03-21
  • 打赏
  • 举报
回复
{ ********************************************************* }
{ 1.我肯定你所说的"类对象的变量名字本来就是一个地址"的说法. }
{ 2.我想对于函数或过程中的形参为对象时, 使用了指向对象的地址}
{ 的方式, 而对象是地址, 即是说使用了指向地址的地址,即C++中的}
{ 二次指针,不知道这样理解对不? 如果真是这样的话, 我知道应该 }
{ 如何修改了,测试代码如下: }
{ ********************************************************* }

var
Form1: TForm1;
FormEdit: TEdit; // 声明全局测试变量


procedure Fun01(Value: TEdit);
//试用带var关键字的声明方式procedure Fun01(var Value: TEdit);
var
TestEdit: TEdit;
begin
TestEdit := TEdit.Create(Form1);
TestEdit.Text := 'in TestEdit';

Value := TestEdit;
if TestEdit = FormEdit then
ShowMessage('相等')
else
ShowMessage('不等');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
FormEdit := TEdit.Create(Self);
FormEdit.Text := 'in FormEdit';
Fun01(FormEdit);
//1.带var的声明方式, 显示"相等"以及"in TestEdit"
//2.不带var的声明方式,显示"不等"以及"in FormEdit",FormEdit没被过程调用修改过
ShowMessage(FormEdit.Text);

end;
mylovelypig 2007-03-21
  • 打赏
  • 举报
回复
哦,你在FormClass.CRMCreate(Application, InitCode);时,使用的是TCRMForm类的构造方法,而TCRMForm类没有TfrmCustList的Panel1这个成员。
========================================
我个人的看法,其实并不象你所说的那样.
OpenForm(TfrmCustList, frmCustList, 'TestCode');
在这个语句后加一条语句检测你就知道,
if Assigned(frmCustList) then
ShowMessage('OK')
else
ShowMessage('NO')

1.frmCustList是类TfrmCustList的对象,而TfrmCustList从TCRMForm继承,TfrmCustList继承了CMCreate构造函数,而我在实例对象frmCustList中使用Panel1应该是没有问题的;

2.你会发觉frmCustList还只是处于声明状态,根本还没有实例化,所以编译时没有出错,但是运行期时试图使用一个未实例化的对象就出错了!


mylovelypig 2007-03-21
  • 打赏
  • 举报
回复
好像有内在泄露吧?
=======================
为了测试,没考虑那么多!其实我贴出的样例代码中有多次存在内存泄露!!!
不过还是多谢提醒:)

真诚感谢 lihuasoft(学习低调做人) 的热心讨论:)

问题已经解决,晚上结贴.
lihuasoft 2007-03-20
  • 打赏
  • 举报
回复
哦,你在FormClass.CRMCreate(Application, InitCode);时,使用的是TCRMForm类的构造方法,而TCRMForm类没有TfrmCustList的Panel1这个成员。

绕来绕去绕得我好晕...
lihuasoft 2007-03-20
  • 打赏
  • 举报
回复
不要用TForm类测试。别忘了,TForm对象在实现时是有一个*.dfm文件的
(个人浅见)
mylovelypig 2007-03-20
  • 打赏
  • 举报
回复
//首先多谢上面的两位,其实我真搞不懂,为什么变量没有被初始化,代码如下,还拜托看下:

// ************ begin CRMFormUnit.pas ************
type
TCRMFormClass = class of TCRMForm;

TCRMForm = class(TForm)
protected
// other method
public
FInitCode: string;
constructor CRMCreate(AOwner: TComponent; InitCode: string);
end;

constructor TCRMForm.CRMCreate(AOwner: TComponent; InitCode: string);
begin
inherited Create(AOwner);
FInitCode := InitCode;
end;

//一系列从TCRMForm继承的窗体全使用这个函数打开,并在创建的时候初始化一些字段
procedure OpenForm(FormClass: TCRMFormClass; FormName: TCRMForm; InitCode: string);
begin
FormName := FormClass.CRMCreate(Application, InitCode);
FormName.Show;
// others
end;

// ************ end CRMFormUnit.pas ************

// ************ begin frmCustList.pas ************
type
TfrmCustList = class(TCRMForm)
Panel1: TPanel;
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmCustList: TfrmCustList;

// ************ end frmCustList.pas ************


// ************ begin frmMain.pas ************
type
TfrmMain = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmMain: TfrmMain;


procedure TfrmMain.Button1Click(Sender: TObject);
begin
OpenForm(TfrmCustList, frmCustList, 'TestCode');
frmCustList.Panel1.Caption := 'OK'; //好象frmCustList没有被赋值并初始化,出错

end;

// ************ end frmMain.pas ************

lihuasoft 2007-03-20
  • 打赏
  • 举报
回复
楼主可以把我的Test过程改为:

procedure Test(E : TEdit);
begin
ShowMessage(Format('%x',[integer(E)]));
E.Text := 'Tested';
end;

然后,把Button1OnClick事件代码中Test(E2);这句后面加上一句:

ShowMessage(E2.Text);

看一下,是不是。
lihuasoft 2007-03-20
  • 打赏
  • 举报
回复
给楼主一段测验代码:

procedure Test(E : TEdit);
begin
ShowMessage(Format('%x',[integer(E)]));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
E1,E2 : TEdit;
begin
E1 := TEdit.Create(self);
E2 := TEdit.Create(self);
E1.Left := 20;
E2.Left := 200;
E1.Text := 'Edit1';
E2.Text := 'Edit2';
E1.Parent := self;
E2.Parent := self;
E1 := E2;
showmessage(Format('E1.Text=%s, E2.Text=%s',[E1.Text,E2.Text]));
E2.Text := 'Changed';
showmessage(Format('E1.Text=%s, E2.Text=%s',[E1.Text,E2.Text]));

ShowMessage(Format('%x',[integer(E2)]));
Test(E2);
end;
lihuasoft 2007-03-20
  • 打赏
  • 举报
回复
TO : 楼上的(楼主)

类对象的变量名字本来就是一个地址。 Test1 := Test2;时,只是把Test1指向了Test2,并没有“复制”一个对象。
还是因为“类对象的变量名字本来就是一个地址”,所以procedure TestFun(Test: TTest1);就已经是传址了,不会在过程内部生成一个对象的副本。
mylovelypig 2007-03-20
  • 打赏
  • 举报
回复
TO:楼上的
我要使用这样的方式来初始化实参的变量!
阿发伯 2007-03-20
  • 打赏
  • 举报
回复

procedure TestFun(var Test: TTest1);
begin

end;

改为


procedure TestFun(Test: TTest1);
begin

end;

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧