Delphi结构体的扩展,可以自动初始化,反初始化,自定义拷贝函数.
转载:http://www.raysoftware.cn/?p=518&utm_source=tuicool
恭贺Delphi XE7诞生,Delphi XE7在编译器内部集成了我之前所实现的动态数组扩展.http://www.raysoftware.cn/?p=278
现在有一个更悠久的历史需求,在QC的Delphi板块上置顶了好多年.官方一直没有实现.
http://qc.embarcadero.com/wc/qcmain.aspx?d=21729
众所周知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两次
代码链接
Source
Delphi结构体的扩展,可以自动初始化,反初始化,自定义拷贝函数.的更多相关文章
- socket编程相关的结构体和字节序转换、IP、PORT转换函数
注意:结构体之间不能直接进行强制转换, 必须先转换成指针类型才可以进行结构体间的类型转换, 这里需要明确的定义就是什么才叫强制转换. 强制转换是将内存中一段代码以另一种不同类型的方式进行解读, 因此转 ...
- Delphi结构体数组指针的问题
//这段代码在Delphi 2007和delphi 7下是可以执行的,所以正确使用结构体数组和指针应该是这样的,已验证 unit Unit1; interface uses Windows, Mess ...
- 【30天自制操作系统】day05:结构体、文字显示与 GDT/IDT 初始化
输出一个 16 行 8 列的点阵字符 void putfont8(char *vram, int xsize, int x, int y, char c, char *font) { int i; c ...
- delphi 结构体和TList的用法
type PRecord = ^TMyRec; TMyRec = record s: string[8]; i: integer; d: double;end;var MyL ...
- 使用 CustomScript 扩展程序自动执行 Linux 虚拟机自定义任务
NingKuangWSSC WS ARD 高级项目经理 您可能已经从Windows扩展程序博客中了解了针对 Windows 虚拟机的 CustomScript扩展程序,现在的好消息是,这一扩展程序也已 ...
- 【2016-08-18】转载:总结C++中几种结构体初始化的方法
作者:Ac_Von 博客地址:http://www.cnblogs.com/vongang/ 文章地址:http://www.cnblogs.com/vongang/archive/2011/07/3 ...
- C基础--结构体成员初始化方式
之前在linux内核代码中看到结构体成员成员初始化使用类似于.owner = THIS_MODULE, 不太见过,于是搜了个博客,分享下: 转自:http://www.cnblogs.com/Anke ...
- Swift - 2 (?和!、结构体、类、协议、扩展、闭包)
1> 可选类型(?)和强制解包(!) 在swift中,可选类型(?) 其根源是一个 枚举型,里面有 None 和 Some 两种类型.其实所谓的 nil 就是 Optional.None , 非 ...
- Linux下C结构体初始化[总结]
1.前言 今天在公司看一同事写的代码,代码中用到了struct,初始化一个struct用的是乱序格式,如下代码所示: typedef struct _data_t { int a; int b; }d ...
随机推荐
- 自然语言13_Stop words with NLTK
https://www.pythonprogramming.net/stop-words-nltk-tutorial/?completed=/tokenizing-words-sentences-nl ...
- CPU绑定操作
使用virsh vcpuinfp命令查看虚拟机VCPU和物理CPU的对应关系 [root@svn ~]# virsh vcpuinfo 16 VCPU: 0 CPU: 3 状态: running CP ...
- apache外网不能访问分析与解决方法
apache安装好以后,在本机可以用:http://localhost 或者 http://127.0.0.1进行访问,但是,在外网(相对本机来说的,局域网也算)不能访问. 这种情况可以分为两个问题, ...
- mysql中set autocommit=0与start transaction区别
set autocommit=0,当前session禁用自动提交事物,自此句执行以后,每个SQL语句或者语句块所在的事务都需要显示"commit"才能提交事务. start tra ...
- NetBeans如何关联两个项目
在实际工作中,有的项目需要关联其他项目 找到项目-->右键-->属性-->包含路径-->添加文件夹 添加你要的项目即可.
- 优化 PHP 代码建议
1.如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍.2.$row[’id’] 的速度是$row[id]的7倍.3.echo 比 print 快,并且使用echo的 ...
- JDBC:从数据库中取数据的一个bug
先看错误信息: java.sql.SQLException: Before start of result set at com.mysql.jdbc.SQLError.createSQLExcept ...
- 开始使用pycharm了
我将python的主力开发工具从eclipse+pydev切换到pycharm社区版了. 选择pycharm 的原因:1. pycharm可以实时按照pep8的规范检查code style和namin ...
- firefox浏览器不能使用window.close的解决方案
javascript中window.close()函数用来关闭窗体,而且IE.google.firefox浏览均支持,但由于firefox浏览器dom.allow_scripts_to_close_w ...
- javacomm64位用不了,可以使用RXTXcomm for x64
安装完后把导入包名改一下就行了! 附上读串口代码: /* * @(#)SimpleRead.java 1.12 98/06/25 SMI * * Copyright (c) 1998 Sun Micr ...