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 ...
随机推荐
- Java——菜单组件
import java.awt.Container; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; i ...
- Orchard源码分析(5.1):Host初始化(DefaultOrchardHost.Initialize方法)
概述 Orchard作为一个可扩展的CMS系统,是由一系列的模块(Modules)或主题(Themes)组成,这些模块或主题统称为扩展(Extensions).在初始化或运行时需要对扩展进行安装:De ...
- CentOs图形界面的开启与关闭
1.1 shell中运行 init 3 进入文本模式,同时会关闭相关的服务(Xserver 肯定关闭) 1.2 Alt+Ctrl+F1~F6到字符界面,root登陆,ps aux|grep /usr ...
- TCSQL实时列表缓存数据库帮助文档
[文章作者:张宴 本文版本:v1.1 最后修改:2010.09.03 转载请注明原文链接:http://blog.zyan.cc/tcsql/] 曾经有人提出,一般数据库缓存分为四种.第一种:单个对象 ...
- axure新手入门教程
首先做个声明:此次教程里为了快速完成,借用了一些网上已有教程的图文,不是剽窃,只图方便.另外,因为汉化版本可能功能名称等略有差别,请自行理解. 名词解释: 线框图:一般就是指产品原型,比如:把线框图尽 ...
- [CentOS7]安装mysql遇到的问题
摘要 在安装mysql的时候,遇到了一些问题,这里列出所遇到的问题. yum list mysql-server 在使用命令yum list mysql-server安装mysql的时候,遇到如图所示 ...
- 正则表达式基础---转自 Python正则表达式指南 前边
1. 正则表达式基础 1.1. 简单介绍 正则表达式并不是Python的一部分.正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十 ...
- oracle vm virtualbox右ctrl切换显示模式
转自: http://blog.csdn.net/lyc_daniel/article/details/44195515 virtualbox里面有个HOME键,注意这个HOME键不一定是键盘上的HO ...
- webpack构建与loaders
loaders 定义 先了解一下webpack,webpack是一个用于针对js文件的构建工具,在被构建的js文件中,我们可以使用require语句和webpack loader,如下: var cs ...
- 采用ETL with RDBMS模式来实现ETL
目前Teradata数据仓库的ETL作业采用ELT方式, 因为loading太重了, 需要将ETL压力转移到专门的ETL Server上. 对于ETL工具, 市场上已有很成熟的商业/开源工具, 比如I ...