Delphi结构体的扩展,可以自动初始化,反初始化,自定义拷贝函数.
文章转贴,原文地址为http://www.raysoftware.cn/?p=518
众所周知Delphi的record和CPP的struct是有区别的.CPP的struct可以看成是class的别名,可以有构造,析构,可以继承.
Delphi的record几年前开始支持方法,支持操作符重载,美中不足之处在于不能自己写默认构造函数.Delphi的帮助文档说可以自己写有参数的constructor但是不能写不带参数的constructor/destructor.但是实际上除非是有引用类型变量,否则结构体不会被初始化.
这就产生了一些问题,
比如说我要借助record的操作符重载,重载+,:=等操作符,自己实现一个string record.但是这个record每次声明以后必须要手动初始化一下,否则里面的内容未被初始化,是随机值.
1 2 3 4 5 | TString = record </pre> len : Integer ; //这个不会被自动初始化 data : pchar ; //这个不会被自动初始化 class operator Add(a, b: TString ): TString; end ; |
实现了一个结构体的初始化,反初始化,拷贝的自动调用单元.
只要你的结构体引用了AutoRecord这个类型的变量,那么结构体就可以自动调用初始化,反初始化,拷贝.
比如:
1 2 3 4 5 6 7 8 | 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在使用的时候就会自动调
1 2 3 4 5 6 7 | 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
总之,编译器不支持的话就要受上面的限制,就当给大家玩玩.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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两次 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!