• Delphi结构体的扩展,可以自动初始化,反初始化,自定义拷贝函数.


    文章转贴,原文地址为http://www.raysoftware.cn/?p=518

    众所周知Delphi的record和CPP的struct是有区别的.CPP的struct可以看成是class的别名,可以有构造,析构,可以继承.
    Delphi的record几年前开始支持方法,支持操作符重载,美中不足之处在于不能自己写默认构造函数.Delphi的帮助文档说可以自己写有参数的constructor但是不能写不带参数的constructor/destructor.但是实际上除非是有引用类型变量,否则结构体不会被初始化.
    这就产生了一些问题,
    比如说我要借助record的操作符重载,重载+,:=等操作符,自己实现一个string record.但是这个record每次声明以后必须要手动初始化一下,否则里面的内容未被初始化,是随机值.

    TString = record</pre>
       len : Integer; //这个不会被自动初始化
       data : pchar; //这个不会被自动初始化
       class operator Add(a, b: TString ): TString; 
    end; 
    

    实现了一个结构体的初始化,反初始化,拷贝的自动调用单元.
    只要你的结构体引用了AutoRecord这个类型的变量,那么结构体就可以自动调用初始化,反初始化,拷贝.
    比如:

    TTest = record
        _ : AutoRecord;
        procedure Operator_Initialize(); //初始化
        procedure Operaor_Finalize(); //反初始化
        procedure Operator_Assign(const source: TTest); overload;//拷贝 :=
        procedure Operator_Assign(const source: TTest; defaultAssign :         
       TDefaultAssign(*调用默认赋值的函数*)); overload;//拷贝 :=
    end;
    

    这样TTest在使用的时候就会自动调

    var
      Test : TTest;
      TestArray : array[0..1] of TTest;
    begin //Test.Operator_Initialize();TestArray[0].Operator_Initialize();TestArray[1].Operator_Initialize();
    ........
      Test := TestArray[0]; //test.Operator_Assign(TestArray[0]);
    end;//Test.Operator_Finalize();TestArray[0].Operator_Finalize();TestArray[1].Operator_Finalize();
    

    注释中是自动被调用的代码.好玩吧.
    有了这几个功能,智能指针也可以做出来.

    不过还有几个限制,是受Delphi编译器的限制.没法实现.
    1.不能是全局变量.全局变量是编译器负责初始化的.数据直接写在PE文件的数据段.
    2.不能是类的成员变量.Delphi的TObject.InitInstance只是简单地FillChar(Instance^, InstanceSize, 0);而不再理会里面的成员.
    3.不能是该类型的动态数组,动态数组的初始化也就仅仅是FillChar为0

    总之,编译器不支持的话就要受上面的限制,就当给大家玩玩.

    uses
      AutoRecords;
    type
      TTest = record
        _: AutoRecord;
        i, j, k: Integer;
        len: Integer;
        P: PByte;
        procedure Operator_Initialize(); // 初始化
        procedure Operaor_Finalize(); // 反初始化
        procedure Operator_Assign(const source: TTest); overload; // 拷贝 :=
      end;
     
      { TTest }
     
    procedure TTest.Operaor_Finalize;
    begin
      FreeMem(P);
    end;
     
    procedure TTest.Operator_Assign(const source: TTest);
    begin
      Move(source.P^, P^, len);
      i := source.i + 100;
      j := source.j * 5;
      k := source.k;
    end;
     
    procedure TTest.Operator_Initialize;
    begin
      i := 0;
      j := 1;
      k := 2;
      len := 100;
      GetMem(P, len);
    end;
     
    procedure TForm5.Button1Click(Sender: TObject);
    var
      a: array [0 .. 1] of TTest;
    begin // 会调用TTest.Operator_Initialize两次
      a[0] := a[1]; // 会调用Operator_Assign
    end; // 会调用TTest.Operaor_Finalize两次
    

      

      

  • 相关阅读:
    equals 和 == 的区别
    jenkins
    状态码
    对控制反转和依赖注入的突然顿悟
    分布式事务与Seate框架
    synchronized原理
    VS 添加 Sqlserver
    C# 生成二维码
    jQuery /Date(0000000000000)/日期转换
    什么是Java的序列化,在哪些程序中见过Java序列化?
  • 原文地址:https://www.cnblogs.com/sttchengfei/p/10459384.html
Copyright © 2020-2023  润新知