鼓励,很多的,Delphi高手突破,外加冷水一瓢

原创 2002年02月21日 15:45:00

很久没有来了,正好来了,正好看了,Delphi高手突破,http://www.csdn.net/Develop/Read_Article.asp?id=12285

正好我也在动手写点东西,hahaha.

有些话要说,不说如鲠在喉。当然,我不会说太多,话多是水。但是,为了方便,我还是将原文部分内容加上。

关于对象内存的分配及回收

不知道有人对dl这个寄存器放在这里有什么想法没有,没有的话就想想,想好了,您就好了。实际上在下面的代码(一)之前,有这样一行代码 MOV dl, 1,那么这样说,为什么要这样,原因,不是很简单的简单,代码重复利用。关于此处dl寄存器的使用,Delphi的帮助中有一段介绍,耐心点,自己去找,找到了,您就是高手了。这就是学习,不,学渔,而不是要鱼。borland是这样说的,“我用dl寄存器来存放一个旗标,如果这个值为1,那么我就创建对象,否则,我不会创建对象。”如果您有点朦胧,那就反复想想。如果还没有睁开眼,那么,就看看后面这一段代码(二),别说您没有找到,咳,怎么回事儿,我老是再说废话,保证不说了。

{代码(一)

test dl, dl
jz +$08
add esp, -$10
call @ClassCreate }

{///代码(二)

procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
  Instance: TComponent;
begin
///////  Instance := TComponent(InstanceClass.NewInstance);
  TComponent(Reference) := Instance;
  try
///////   Instance.Create(Self);
  except
    TComponent(Reference) := nil;
    raise;
  end;
  if (FMainForm = nil) and (Instance is TForm) then
  begin
    TForm(Instance).HandleNeeded;
    FMainForm := TForm(Instance);
  end;
end;

这样的话,就是说,Delphi调用代码(一),是在第一次调用创建类的实例的时候,然后,如果,谁还需要调用Create方法,我就,不,是编译器就这样MOV dl, 0,这样代码(一)的判断0跳转指令就会到该去的地方了,(怎么又来废话了,最后一次,我保证。)实际上,这里的Create方法只是一个普通的方法,而且,您应该还注意到,第一个调用Create方法或者NewInstance方法,都是类在发出这个消息,(注意这个消息不是Windows消息,此消息非彼消息,哈哈,又来了废话,真的最后一次了,是真的。如果不理解这里的消息的话,请认真学写面向对象和建模的知识。)而后面调用Create方法却是建立起来的对象,Instance.Create(Self);好好想想,当然dl寄存器的值就变了。

好了,没有什么时间了,最后补充一点,关于旗标(台湾的翻译方法,我认为这个词不错,建议您也使用它,省得以后我多费口舌)和这个dl寄存器的使用说明,应该说不会有什么变化了,仔细想想,Delphi从1到6大方向上就没有变过,顺便也证明了Delphi的HB设计师是个人物啊,当然,我是没法比了。哈哈,又来了,好,我还是不说了。哦,最后,说一句,TObject.Create方法决不是一个空方法,记住,然后,去想。

 

好了,别的东西,麻烦您亲自去看,那样的话,您才有很多很多的收获。

“快滚,我要去看,去想,不要你的废话!”有人在笑!:)

bye

编译器在为对象分配内存时,所提供的支持就是在调用构造函数之前插入这几行汇编代码:

test dl, dl
jz +$08
add esp, -$10
call @ClassCreate // 注意这行代码

以上代码的最后一行代码调用的是system.pas文件的第8949行的_ClassCreate函数(以Delphi 6为准),该函数具体为每个对象分配合适的内存。内存分配完成后是调用类的构造函数以初始化数据成员。之后,编译器会再插入以下几行汇编代码:

test dl, dl
jz +$0f
call @AfterConstruction
pop dword ptr fs:[$00000000]
add esp, $0c

其中主要工作是调用每个对象实例的AfterConstruction,这个调用在Delphi中没有用,它的存在是为C++Builder所保留的。
同样,析构对象时,首先要调用类的析构函数以释放对象申请的资源。之后是回收对象本身所占内存空间,这件工作是由编译器在调用析构函数后,插入以下的汇编代码来完成的:

call @BeforeDestruction
test dl, dl
jle +$05
call @ClassDestroy

这些代码所做的工作与构造对象分配内存时所做的是对应的,主要是对system.pas中第8997行的_ClassDestroy函数的调用。

构造函数与析构函数

定义构造函数使用Constructor关键字,按惯例,构造函数名称为Create(当然也可以用其他名称,但那绝非优良的设计!)。如:

type
 TMyFamily = class  // 为你的家庭定义的类
 Private
  FMyFatherName : String;  // 你父亲的名字
  FMyMotherName : String;  // 你母亲的名字
  …… // 你家庭中的其他成员
 Public
  Constructor Create(strFatherName, strMotherName : String);
  …… // 其它方法
 End;

也许你会问,如果我没有为我的类提供构造函数,它的对象能否被建立呢?答案是:可以。原因前面已经说了,对象本身所占内存的分配是由编译器完成的。而且由于Object Pascal中,所有类(除了TObject类本身)都是从TObject类派生,因此编译器会调用TObject.Create()构造函数,只是这个函数是一个空函数,它并不会对TMyFamily类的数据成员(FMyFatherName、FMyMotherName)初始化,它们会被自动清为空字符串(即''),因为TObject.Create()根本就不认识你的父、母亲!

创建对象时则直接调用构造函数,形式如下:

MyFamilyObject := TMyFamily.Create('Zhang', 'Li');

定义析构函数使用Destructor关键字,按惯例,析构函数名称为Destroy。如:

type
 TMyClass = class
 Public
  Destructor Destroy(); override;
 End;

之所以在析构函数声明最后加上override声明,是因为保证在多态的情况下对象能正确被析构(关于多态,将在2.4节中详述)。如果不加override关键字,编译器会给出类似"Method 'Destroy' hides virtual method of base type 'TObject'"的警告提示。警告的意思是你定义的Destroy隐藏了基类的虚方法TObject.Destroy(),那样的话,在多态的情况下就无法正确析构对象了。

注意:析构函数都需要加override声明。

同样,如果在你的类中没有特殊的资源需要被释放,那么你也可以不定义析构函数。只是,在析构对象的时候,应该调用对象的Free()方法而不是直接调用Destroy()。
MyFamilyObject.Free();
这是因为在Free()方法中会判断对象本身是否为nil,如果不为nil才调用对象的Destroy(),以增加安全性。既然有这样的更安全的做法,当然没有理由不这么做了。
注意:永远不要直接调用对象的Destroy(),而应该是Free()。
由此可以得出结论,在Object Pascal中你只需关注对象所申请的资源的分配与释放,而不必关心对象本身所占空间!

小改进大奖励,大建议只鼓励

公司实行小改进大奖励、大建议只鼓励的制度。追求管理不断的优化与改良,构筑与推动全面最佳化的有引导得到自发的群众运动。 能提大建议的人已不是一般的员工了,也不用奖励,一般员工提大建议,我们不提倡,因为...
  • acrodelphi
  • acrodelphi
  • 2014年08月18日 21:20
  • 1223

IMDB排名前100名经典电影

IMDB中文名称是互联网电影资料库,是目前全球互联网中最大的一个电影资料库,里面包括了几乎所有的电影,以及1982年以后的电视剧集。IMDB的资料中包括了影片的众多信息,演员、片长、内容介绍、分级、评...
  • u011677147
  • u011677147
  • 2015年09月25日 17:38
  • 1604

如何对长期出差的员工进行“人文关怀”,前提是差旅标准仍然很抠?

坦白说听到要连续出差两三个月,期间还不能回家,差旅标准又很低,还来问怎样“人文关怀”员工,我就想开骂了。你能不能学学一些公司,出差期间每周都可以飞机回家(可以报销),实在不行两周回一次家?员工的后顾之...
  • u010825142
  • u010825142
  • 2016年04月12日 17:34
  • 11543

delphi高手突破之异常及错误处理

什么是异常?为什么要用它? 所谓“异常”是指一个异常类的对象。Delphi的VCL中,所有异常类都派生于Exception类。该类声明了异常的一般行为、性质。最重要的是,它有一个Message属性可...
  • sushengmiyan
  • sushengmiyan
  • 2012年04月25日 22:49
  • 1644

【读书笔记】【delphi高手突破】TCanvas与Windows GDI

TCanvas: 一条为图形组件(基类:TGraphicControl) , 一条为窗口组件(基类:TWinControl)。 1,TGraphicControl讲解(Tpen和Tbrush原理基本一...
  • putin1223
  • putin1223
  • 2015年01月06日 14:07
  • 377

【读书笔记】【Delphi高手突破】TControl与Windows消息的封装

今天开始开通博客,写一些读书笔记,用以以后自己便于查阅。 1,VCL类图主要分支 2,TObject与消息分发(万物之源“TObject”的消息机制原理) a:自定义  TMyMsg:记录消...
  • putin1223
  • putin1223
  • 2015年01月05日 17:18
  • 196

【读书笔记】【Delphi高手突破】TCanvas

1,VCL将GDI的设备抽象成一个画布(Canvas) TCanvas = class(TPersistent) private FHandle: HDC; State: TCanvasState;...
  • putin1223
  • putin1223
  • 2015年01月06日 14:48
  • 323

Delphi高手突破

  • 2007年11月28日 00:31
  • 5.77MB
  • 下载

014_《Delphi高手突破》

  • 2010年11月22日 14:52
  • 1.72MB
  • 下载

Delphi高手突破

  • 2011年05月07日 20:20
  • 12.31MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:鼓励,很多的,Delphi高手突破,外加冷水一瓢
举报原因:
原因补充:

(最多只允许输入30个字)