发了上一篇博客.盒子上有朋友认为Class的构造和析构延迟加载.是在Unit的初始化后调用的Class的构造.在Unit的反初始化前调用的Class的析构函数.

为了证明一下我又做了个试验

unit Unit2;

interface

Type
  TClassTest = class
    class constructor create();
    class destructor destory();
  end;

implementation
uses
  Windows;

{ TClassTest }

class constructor TClassTest.create;
begin
  OutputDebugString('class constructor');
end;

class destructor TClassTest.destory;
begin
  OutputDebugString('class destructor');
end;

initialization
   OutputDebugString('Unit initialization');
finalization
   OutputDebugString('Unit finalization');

end.

为了防止编译器因为TClassTest 没有被使用而优化去掉TClassTest .所以我们要用一下TClassTest .

procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := TClassTest.ClassName;

end;

运行,然后退出.在Event Log窗口中我们见到.

可见类的构造是在Unit初始化前被调用,而类的析构则是在Unit的反初始化后被调用的.

Debug Output: class constructor Process Project1.exe (3940)
Debug Output: Unit initialization Process Project1.exe (3940)
Debug Output: Unit finalization Process Project1.exe (3940)
Debug Output: class destructor Process Project1.exe (3940)

进而再看如果是有派生类,祖先类的情况.

unit Unit2;

interface

Type

TClassTestParent = class
    class constructor create();
    class destructor destory();
  end;

TClassTest = class(TClassTestParent)
    class constructor create();
    class destructor destory();
  end;

implementation
uses
  Windows;

{ TClassTest }

class constructor TClassTest.create;
begin
  OutputDebugString('class constructor');
end;

class destructor TClassTest.destory;
begin
  OutputDebugString('class destructor');
end;

{ TClassTestParent }

class constructor TClassTestParent.create;
begin
  OutputDebugString('Parent class constructor');
end;

class destructor TClassTestParent.destory;
begin
 OutputDebugString('Parent class destructor');
end;

initialization
   OutputDebugString('Unit initialization');
finalization
   OutputDebugString('Unit finalization');

end.
那么结果是:

Debug Output: Parent class constructor Process Project1.exe (3256)
Debug Output: class constructor Process Project1.exe (3256)
Debug Output: Unit initialization Process Project1.exe (3256)
Debug Output: Unit finalization Process Project1.exe (3256)
Debug Output: class destructor Process Project1.exe (3256)
Debug Output: Parent class destructor Process Project1.exe (3256)

可见如果存在类的继承关系则规律是

先父类的构造,然后是子类的构造,最后是单元初始化;先单元反初始化,然后是子类析构,最后是父类析构.

然后再进一步测试:

TClassTestA = class
  public
    class constructor create();
    class destructor destory();
  end;

TClassTestB = class
    class constructor create();
    class destructor destory();
  end;

发现同一个单元内多个不相干的类,似乎是后面的类构造函数是和声明次序相反的.析构则是和声明顺序相同

再进一步测试

改造如下代码:

class constructor TClassTestB.create;
begin
  if(TClassTestA.ClassName = '') then
  else
  OutputDebugString('class B constructor');
end;

发现如果一个类的构造中使用了另外的类,那么构造顺序则是先调用被引用类的构造.

这时想起一个有趣的问题,如果循环使用的话会是什么结果呢.我的猜测是或许编译器不会让通过吧.

class constructor TClassTestB.create;
begin
  if(TClassTestA.ClassName = '') then
  else
  OutputDebugString('class B constructor');
end;

class constructor TClassTestA.create;
begin
  if(TClassTestB.ClassName = '') then
  else
  OutputDebugString('class A constructor');
end;

嘿嘿,出乎我的意料.编译竟然通过了.结果是类构造函数循环使用其他的类的话又变成按声明顺序调用类构造函数,按声明顺序相反顺序调用类的析构函数.

最后的规律就是:

1.类析构顺序总是和类构造顺序相反,类的构造总是在单元初始化前被调用.类的析构器总是在单元的反初始化后被调用

2.无关联的情况下按声明的顺序相反调用类构造

3.优先调父类的类构造函数

4.优先调用在类构造析构器中被使用的其他类的类构造

5.如果在类构造析构器循环使用的话按声明的顺序调用类构造器

可能还有其他规律吧.

同时有个额外发现.如果类有构造器析构器的话Delphi编译器的代码提示会有一个诸如TClassTestA.$ClassInitFlag之类的变量提示出来.

而正常的类则不会有这个提示.当然这个东西肯定是不能在代码中使用的,因为"$"在变量名函数名中都是非法的符号.应该是编译器产生的一些符号表标志被提示出来了.呵呵.

http://blog.csdn.net/wr960204/article/details/4525763

最新文章

  1. Spark shuffle详细过程
  2. javascript之小积累-.-添加form表单查询的enter键支持
  3. 探究MaxxBass音效
  4. ubuntu Nodejs和npm的安装
  5. The Automated Testing Handbook 自动化测试手册简介
  6. 最大连续子数和问题-homework-03
  7. poj 2524 Ubiquitous Religions(宗教信仰)
  8. 训练趣题:黑与白 有A、B、C、D、E五人,每人额头上都帖了一张黑或白的纸。(此处用javascript实现)
  9. 减少 WAF 漏报的 8 种方法 !
  10. cocos2dx中Action汇总
  11. Maxmum subsequence sum problem
  12. zf-关于交换工具配置文件,交换的“列名字段”前面加个“0,1,2”的意思。
  13. 运维之Linux基础(二)
  14. 网页如何展示PPT文档
  15. Where Can I Download Full Installers for WebLogic Server
  16. 使用mybatis plus 操作数据库
  17. python - 练习(获取windows硬件信息)
  18. Mybatis批量insert 返回主键值和foreach标签详解
  19. IDEA & Android Studio换主题背景
  20. express 默认模板引擎

热门文章

  1. 解压tomcat后一闪而过的问题
  2. python 32位、64位确定
  3. jquery插件anccordion
  4. 通过 IP 访问谷歌
  5. Hibernate之dynamic-update
  6. PICT安装及使用
  7. classic asp中使用ADODB.Command防止sql injection
  8. 走进C标准库(2)——"stdio.h"中的fopen函数
  9. Glib程序使用Valgrind查找内存泄露
  10. Oracle EBS-SQL (SYS-8):职责定义明细.sql