自定义类 的问题???

okmnji79513 2009-12-23 12:53:39

type
TMy=class
private
FValue:integer;
public
procedure MyTest;
constructor Create(i:integer);
destructor Destroy;override;
end;
PMy=^TMy;

TForm1 = class(TForm)
......
public
procedure My(var msg:TMessage);message WM_My;
end;

......

{TMy}
constructor TMy.Create(i:integer);
begin
inherited Create;
FValue:=i;
Form1.Memo1.Lines.Add('TMy.Create');
end;

destructor TMy.Destroy;//override;
begin
Form1.Memo1.Lines.Add('TMy.Destroy');
inherited;
end;

procedure TMy.MyTest;
begin
Form1.Memo1.Lines.Add('TMy.MyTest - FValue : '+inttostr(FValue));
end;

//************

procedure TForm1.My(var msg:TMessage);
var pmy:PMy;
begin
if msg.WParam=1 then
begin
pmy:=PMy(msg.LParam);
pmy.MyTest;
end;
end;

procedure TForm1.Button15Click(Sender: TObject);
var my:TMy;
begin
my:=TMy.Create(123);
my.MyTest;
PostMessage(handle,WM_My,1,integer(@my));
end;

procedure TForm1.Button16Click(Sender: TObject);
var my:TMy;
begin
my.MyTest;
end;

procedure TForm1.Button17Click(Sender: TObject);
var my:TMy;
begin
my:=TMy.Create(1);
my.MyTest;
my.Free;
end;

按下 Button15 后,打印出信息 如下:

TMy.Create
TMy.MyTest - FValue : 123
TMy.MyTest - FValue : 123

按下 Button16 后,打印出信息 如下:
TMy.MyTest - FValue : 14226404

按下 Button16 后,打印出信息 如下:

TMy.Create
TMy.MyTest - FValue : 1
TMy.Destroy



问题:
1、Button15 结束后,对象“my”有没有被释放掉?为什么不打印“TMy.Destroy”?为什么在 WM_My处理函数中,还能调用MyTest方法 且 打印 结果 正确??
2、为什么 Button16 按下后 ,没有创建对象就直接调用MyTest 却 没有报错,也打印出了信息??且既没有“TMy.Create”也没有“TMy.Destroy”被打印出来??

如上 两点 中 5个问题,请解答,谢谢。
...全文
211 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
wliaoc 2009-12-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lhylhy 的回复:]
1手动创建就要手动释放,有对象就可以调用。
2有函数就成。未创建未释放当然不打印。
[/Quote]

调用对象的私有变量没赋值,所以变量输出是随机数,但是不会报错
okmnji79513 2009-12-24
  • 打赏
  • 举报
回复
UPUP
okmnji79513 2009-12-23
  • 打赏
  • 举报
回复
上面 代码 中 消息处理函数错了,改为:

procedure TForm1.My(var msg:TMessage);
var p:PMy;//pmy 改为 p
begin
if msg.WParam=1 then
begin
p:=PMy(msg.LParam);
p.MyTest;
end;
end;
okmnji79513 2009-12-23
  • 打赏
  • 举报
回复
我写了个这个:

procedure TForm1.Button19Click(Sender: TObject);
var i:integer;
my:TMy;
begin
if my=nil then
memo1.Lines.Add('nil')
else
memo1.Lines.Add('<> nil');
memo1.Lines.Add('integer(My) : '+inttostr(integer(My)));
My.MyTest;
copymemory(@i,pointer(integer(My)+sizeof(pointer)),sizeof(integer));
memo1.Lines.Add('i : '+inttostr(i));
end;

打印出来时这样:

<> nil
integer(My) : 4388748
TMy.MyTest - FValue : -217126717
i : -217126717

说明啥不?
lhy 2009-12-23
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 okmnji79513 的回复:]
引用 14 楼 lhylhy 的回复:
...... 你没有用到对象里的数据......

这什么意思?我不是用到了
private
    FValue:integer;
的吗?

[/Quote]
看错了,是因为指针未赋值时一般为NULL,不会指向未知空间。
林石公 2009-12-23
  • 打赏
  • 举报
回复
"不干寄存器的事,delphi对这种函数的调用就是静态调用,my.MyTest等于是MyTest(my)。"
如果这个成立,你试过多声明几个局部变量没有?在我的机器上,第三个未create的局部变量作MyTest操作时就会出av错误,前两个怎么也不会出错
林石公 2009-12-23
  • 打赏
  • 举报
回复
关于寄存器的结论,我是看单步跟踪时,看CPU的DebugWindows得出的结论,当然,在其它人的机器上可能表现不一样,但我认为道理可能就是这样的,
并不是我想当然的说说而已
另外,大富翁论坛的这个帖子似乎分析的更详细
http://www.delphibbs.com/keylife/iblog_show.asp?xid=31260
lhy 2009-12-23
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 sonicer 的回复:]
跟踪一下,看看汇编代码就明白了
[/Quote]
寄存器当然用到了,可是不出错的原因和寄存器无关。
okmnji79513 2009-12-23
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 sonicer 的回复:]
跟踪一下,看看汇编代码就明白了
[/Quote]
看过,没看懂
林石公 2009-12-23
  • 打赏
  • 举报
回复
跟踪一下,看看汇编代码就明白了
okmnji79513 2009-12-23
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 lhylhy 的回复:]
...... 你没有用到对象里的数据......
[/Quote]
这什么意思?我不是用到了
private
FValue:integer;
的吗?
lhy 2009-12-23
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 sonicer 的回复:]
DELPHI在能用寄存器时决不用堆栈
所以button16那样的方式,可以成功,
据我观察,在我的机器上,类似的变量可以定义两个,

var my, my2:TMy;
begin
  my.MyTest; //esi
  my2.MyTest;//edi
end;
//因为esi, edi里一般都是有值的,不会被判定为nil,cpu根据里边的值(希望没指向一个无法访问的地址啊),相对的根据位移,找到Finteger对应地址,取出值来,这样是说的过去的
这样仍然行的通,但如果你再多定义一个,my3:Tmy,就不行了,寄存器不够用的了,这时就用到ebp-xx这样的堆栈值了,那时就AV了,因为堆栈上的事就不好说了
另外,EBX寄存器可能让self偷偷的占去了

[/Quote]
不干寄存器的事,delphi对这种函数的调用就是静态调用,my.MyTest等于是MyTest(my)。
lhy 2009-12-23
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 harryfin 的回复:]
16那里不出错纯粹是碰巧而已
[/Quote]
不是碰巧,他那个函数不用到对象里的数据,也不用到vtable,所以不出错。
delphi在这种情况下的调用纯粹就是静态调用而已。
lhy 2009-12-23
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 okmnji79513 的回复:]
to wzwcn
多谢了,脑子一团乱。


那个Button16,为什么只要“有函数就成”?能讲解讲解不?
[/Quote]
涉及到Delphi的对象模型。
像这种调用,一般是直接调用这个函数,把对象当做隐含参数传递给函数,你没有用到对象里的数据,当然不出错。
wxsan 2009-12-23
  • 打赏
  • 举报
回复
看看
ok1411 2009-12-23
  • 打赏
  • 举报
回复
路过,学习了
林石公 2009-12-23
  • 打赏
  • 举报
回复
DELPHI在能用寄存器时决不用堆栈
所以button16那样的方式,可以成功,
据我观察,在我的机器上,类似的变量可以定义两个,

var my, my2:TMy;
begin
my.MyTest; //esi
my2.MyTest;//edi
end;
//因为esi, edi里一般都是有值的,不会被判定为nil,cpu根据里边的值(希望没指向一个无法访问的地址啊),相对的根据位移,找到Finteger对应地址,取出值来,这样是说的过去的
这样仍然行的通,但如果你再多定义一个,my3:Tmy,就不行了,寄存器不够用的了,这时就用到ebp-xx这样的堆栈值了,那时就AV了,因为堆栈上的事就不好说了
另外,EBX寄存器可能让self偷偷的占去了
Harryfin 2009-12-23
  • 打赏
  • 举报
回复
16那里不出错纯粹是碰巧而已
wzwcn 2009-12-23
  • 打赏
  • 举报
回复
Button16那样调竟然不出错我也不清楚原因,不过自己平时不要那样用就行了。记得对象一定要创建才能使用,使用完要释放掉就行了
okmnji79513 2009-12-23
  • 打赏
  • 举报
回复
to wzwcn
多谢了,脑子一团乱。




那个Button16,为什么只要“有函数就成”?能讲解讲解不?
加载更多回复(6)

16,748

社区成员

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

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