一个很简单的Edit组件赋值问题。

OO_is_just_P 2008-08-26 08:36:14
四个button,2个Edit,哪位给讲解一下,我准备了板凳。

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2 :=Edit1;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
FreeAndnil(Edit1);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
FreeAndnil(Edit2);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
if Edit1=nil then
showMessage('Edit1=nil');
if Edit2=nil then
showMessage('Edit2=nil');
if (Edit1 is TEdit) then
showMessage('Edit1 is TEdit');
if (Edit2 is TEdit) then
showMessage('Edit2 is TEdit');
end;

end.
...全文
229 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
王集鹄 2008-08-31
  • 打赏
  • 举报
回复
其实楼主在12楼已经猜到了,,,“和RTTI有关”[img=http://p.blog.csdn.net/images/p_blog_csdn_net/zswang/%E5%9B%A7.gif]图[/img]
lihuasoft 2008-08-30
  • 打赏
  • 举报
回复
看来,只要细心慢慢找,大多数(不是全部)问题的答案都在VCL源码中。

谢谢Zswang负责任地给本贴延伸的第二个问题以完美的答案。

同时,这第二问题解决后,也证明我在5楼的某些说法是不恰当的(想多了),楼主原问题的答案应回归2楼。

^_^
王集鹄 2008-08-30
  • 打赏
  • 举报
回复
其实开始一直没有看明白题目,还是昨天和lihuasoft一起调试代码才搞明白问题。

当碰到这个问题的时候,我头晕了一阵。

真是出现了很多星星。。。。procedure TForm1.Button1Click(Sender: TObject);
type PComponentName = ^TComponentName;
begin
PComponentName(@Edit2.Name)^ := 'Edit1';
Edit2.Free;
OutputDebugString(PChar(Format('Edit1 %p', [Pointer(Edit1)])));
end;

我们来看这代码,Edit2.Free导致Edit1变成nil,,,是的因为,Name,嘿嘿。。。

到VCL调试这段代码
procedure TComponent.SetReference(Enable: Boolean);
var
Field: ^TComponent;
begin
if FOwner <> nil then
begin
Field := FOwner.FieldAddress(FName);
if Field <> nil then
if Enable then Field^ := Self else Field^ := nil;
end;
end;


看看载入窗体资源的堆栈:
[img=http://p.blog.csdn.net/images/p_blog_csdn_net/zswang/EntryImages/20080830/SetReference.GIF" alt="" />

看看释放元件的堆栈:
TComponent.SetReference(False)
TComponent.RemoveComponent(...)
TComponent.Destroy
TControl.Destroy
TWinControl.Destroy
TObject.Free
...


总结:设计期间创建的元件,即存在窗体资源(.dfm)中的元件,当这类元件被释放的时候,相应的窗体字段也会被赋值为空。
详细过程参考TComponent.SetReference()方法。

楼主可以结贴了。[img=http://p.blog.csdn.net/images/p_blog_csdn_net/zswang/%E5%90%B8%E7%83%9F.gif]图[/img]
qjinshanq 2008-08-30
  • 打赏
  • 举报
回复
好好用心学习!
OO_is_just_P 2008-08-30
  • 打赏
  • 举报
回复
谢谢zswang 来讲课,受用了。
手指风 2008-08-29
  • 打赏
  • 举报
回复
其实是delphi的语法把指针的概念都弱化了,而且如下的语句编译都通过,且效果一样.

Type
PRecData = ^TRecData;
TRecData = record
Str : string;
end;

var
P:PRecData;
begin
try
new(P);
P.Str := 'aaa'; //以下2句
P^.Str := 'bbb'; //
finally
Dispose(P);
end;
end;
jmxb123 2008-08-29
  • 打赏
  • 举报
回复
偶也回复一下,以后找这个帖子比较容易 方便学习
lihuasoft 2008-08-28
  • 打赏
  • 举报
回复
从伴水那里找到答案了:

“字段的地址,一直不会变”

终于明白嘹

嘿嘿,感谢。感谢伴水解惑,感谢楼主提出题目。
lihuasoft 2008-08-28
  • 打赏
  • 举报
回复
to 伴水:

再看看....11楼提出的问题....

有了答案,贴在这里也可,在QQ上给我留言也可......

谢了....害您老晚饭没吃安顿..
lihuasoft 2008-08-28
  • 打赏
  • 举报
回复
既然楼主已经开始公布标准答案,那就请教一下:

为什么FreeAndNil(Edit2)会将Edit2、Edit1的指针值都置为nil
而FreeAndNil(Edit1)只能将Edit1置为nil?

Delphi又是怎么实现这个的?
lihuasoft 2008-08-28
  • 打赏
  • 举报
回复
^_^

我就估计楼主是“准备了板凳”来讲课的

当初直接开一个教学贴多好!
王集鹄 2008-08-28
  • 打赏
  • 举报
回复
FreeAndNil的源代码就摆在这里,有啥好研究的?
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;


测试一下就知道了,测试的结果说明一切。[img=http://p.blog.csdn.net/images/p_blog_csdn_net/zswang/%E5%9B%A7.gif]图[/img]
OO_is_just_P 2008-08-28
  • 打赏
  • 举报
回复
哈哈,谢谢大家关注!
TO:1L,不变态能引起讨论吗?
我觉得EDIT1,EDIT2都是对象的指针(OOP叫实例吧,但本质是指针)而已,指向一个Tedit类型的空间。
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2 :=Edit1;
end;
后,Edit2指向EDIT1所指向的地址,此时原来EDIT2的地址没有保存,丢失了。
procedure TForm1.Button2Click(Sender: TObject);
begin
FreeAndnil(Edit1);
end;
后,Edit1指向的TEDIT类实例释放,同时EDIT1赋值Nil,EDIT2也是指向了一个不存在的实例,但没有置nil.此时:
procedure TForm1.Button3Click(Sender: TObject);
begin
FreeAndnil(Edit2);
end;
出错。
procedure TForm1.Button4Click(Sender: TObject);
begin
if Edit1=nil then
showMessage('Edit1=nil');
if Edit2=nil then
showMessage('Edit2=nil');
if (Edit1 is TEdit) then
showMessage('Edit1 is TEdit');
if (Edit2 is TEdit) then
showMessage('Edit2 is TEdit');
end;
应该显示消息'Edit1=nil'
'Edit2 is TEdit'因为其没置nil.
而表现在程序窗口上,虽然Edit2指向了其它地址,但是原来所建立的TEDIT类没有释放,所以在主窗口上EDIT2还是存在的。
我理解的不对的地方欢迎指正。

OO_is_just_P 2008-08-28
  • 打赏
  • 举报
回复
不知道,没研究过!
procedure TForm1.Button1Click(Sender: TObject);
var a,b:TEdit;
begin
a :=Edit1;
b :=a;
freeandnil(b);
if a=nil then
showmessage('a is nil');
if b=nil then
showMessage('b is nil');
end;
这个只有b是nil;
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
应该不是FreeAndNil造成的,应该和RTTI有关。
lihuasoft 2008-08-27
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zzflover 的回复:]
edit2:=edit1;释放了edit1再释放edit2就出错了。这么理解对不对?
[/Quote]

这样说至少没有错。因为您描述的是这个程序的表象。
7年 2008-08-27
  • 打赏
  • 举报
回复
edit2:=edit1;释放了edit1再释放edit2就出错了。这么理解对不对?
lihuasoft 2008-08-27
  • 打赏
  • 举报
回复
楼主失踪了?
一起将话题讨论下去啊
lihuasoft 2008-08-26
  • 打赏
  • 举报
回复
我在二楼的注释中有一部分应该改一下:


procedure TForm1.Button2Click(Sender: TObject);
begin
FreeAndnil(Edit1);
{此时,AAA已经被释放,并且Edit1的指针值被赋值为nil}
{但是,此时Edit2的值并不是nil,尽管它所指向的AAA已经被释放}
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
{如果先执行FreeAndnil(Edit1);再执行下面这句,必然导致一个错误
因为Edit2此时不是nil,但它指向的AAA已经释放
如果先执行FreeAndnil(Edit2);则Edit1和Edit2同时变为nil,
因为:在Edit2 := Edit1的赋值的时候,不仅仅是指针值的赋值,同时Edit2作为了Edit1的“引用”!
因此,先执行下面这句,再执行FreeAndnil(Edit1);就不会出错了}
FreeAndnil(Edit2);
end;
lihuasoft 2008-08-26
  • 打赏
  • 举报
回复
PS:

上面注释是假定按 Button1--> Button2 --> Button3 ---> Button5 ---> Button4的顺序Click的
pathletboy 2008-08-26
  • 打赏
  • 举报
回复
Edit1,Edit2都是对象指针,改了指针的值,实际的存储空间还在。
加载更多回复(2)

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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