转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
《delphi高手突破》节选一         ★★★★

《delphi高手突破》节选一

作者:闵涛 文章来源:闵涛的学习笔记 点击数:701 更新时间:2009/4/23 18:39:55

上次贴出新书的第一章,出乎我的意料,反响热烈,得到许多网友的支持。
今天完成了第二章的草稿的撰写,在此节选一小段文字,希望继续得到大家的支持,指正。
当然,节选的量是非常少的(否则出版社也不答应,呵呵),不过,一斑可窥全豹,之后我会在每一章完成后,节选少量文字贴在这里。

信箱 nicrosoft@sunistudio.com
个人主页 http://www.sunistudio.com/nicrosoft/
东日制作室 http://www.sunistudio.com

===========================================================

在Object Pascal中,所有对象都被建立在内存的堆空间上,而非栈上,因此构造函数不会如同C++那样被编译器自动调用。构造对象和析构对象都是程序员的职责。
构造对象首先要为对象分配内存,这个步骤在Object Pascal中是由编译器支持完成的--即所谓的"编译器魔法(Compile Magic)",此过程程序员不必参与;接着要初始化对象的数据成员,编译器会负责"清零",但如果有特殊的赋值,可以在构造函数中完成;对象在被析构的时侯需要释放所申请的资源(非对象本身所占用内存),这些工作是析构函数的职责;对象本身所占内存的回收,同样由"编译器魔法"完成。

对象内存的分配及回收

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

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中你只需关注对象所申请的资源的分配与释放,而不必关心对象本身所占空间!


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台