zoukankan      html  css  js  c++  java
  • 再探Delphi2010 Class的构造和析构顺序

    发了上一篇博客.盒子上有朋友认为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

  • 相关阅读:
    Linux下管道编程
    【Windows】用信号量实现生产者-消费者模型
    初识【Windows API】--文本去重
    HDU 5183 Negative and Positive (NP) --Hashmap
    【ASC 23】G. ACdream 1429 Rectangular Polygon --DP
    UVALive 4670 Dominating Patterns --AC自动机第一题
    POJ 2225 / ZOJ 1438 / UVA 1438 Asteroids --三维凸包,求多面体重心
    我也来写2014年总结
    UVALive 4870 Roller Coaster --01背包
    UVALive 4864 Bit Counting --记忆化搜索 / 数位DP?
  • 原文地址:https://www.cnblogs.com/findumars/p/5037487.html
Copyright © 2011-2022 走看看