Delphi的运算符重载

使用Delphi编写游戏,唯一没有C++方便的就是不支持运算符重载。当你编写有关向量或者矩阵计算的程序时,不支持运算符重载的Delphi使用起来是很费劲的。

但是Delphi 2006改变了这种局面,新的Delphi内核已经支持运算符重载了!

本文将介绍如何使用Delphi的运算符重载功能

注意:只有Delphi 2006 和 免费版的 Turbo Delphi 支持这一功能!

Delphi for Win32 只支持 record 类型的运算符重载,而 Delphi .NET 还支持 class 类型的运算符重载

下面是Delphi支持的可重载运算符

运算符 类型 声明语法 应用符号

Implicit 转换 Implicit(a: type): resultType; 隐式转换

Explicit 转换 Explicit(a: type): resultType; 显式转换

负 一元运算 Negative(a: type): resultType; -

正 一元运算 Positive(a: type): resultType; +

递增 一元运算 Inc(a: type): resultType; Inc

递减 一元运算 Dec(a: type): resultType; Dec

逻辑非 一元运算 LogicalNot(a: type): resultType; not

按位非 一元运算 BitwiseNot(a: type): resultType; not

截取 一元运算 Trunc(a: type): resultType; Trunc

舍入 一元运算 Round(a: type): resultType; Round

等于 比较 Equal(a: type; b: type) : Boolean; =

不等于 比较 NotEqual(a: type; b: type): Boolean; <>

大于 比较 GreaterThan(a: type; b: type) Boolean; >

大于等于 比较 GreaterThanOrEqual(a: type; b: type): resultType;>=

小于 比较 LessThan(a: type; b: type): resultType; <

小于等于 比较 LessThanOrEqual(a: type; b: type): resultType; <=

加 二元运算 Add(a: type; b: type): resultType; +

减 二元运算 Subtract(a: type; b: type): resultType; -

乘 二元运算 Multiply(a: type; b: type): resultType; *

除 二元运算 Divide(a: type; b: type): resultType; /

整除 二元运算 IntDivide(a: type; b: type): resultType; div

模 二元运算 Modulus(a: type; b: type): resultType; mod

左移 二元运算 ShiftLeft(a: type; b: type): resultType; shl

右移 二元运算 ShiftRight(a: type; b: type): resultType; shr

逻辑与 二元运算 LogicalAnd(a: type; b: type): resultType; and

逻辑或 二元运算 LogicalOr(a: type; b: type): resultType; or

逻辑异或 二元运算 LogicalXor(a: type; b: type): resultType; xor

按位与 二元运算 BitwiseAnd(a: type; b: type): resultType; and

按位或 二元运算 BitwiseOr(a: type; b: type): resultType; or

按位异或 二元运算 BitwiseXor(a: type; b: type): resultType; xor

在具体介绍如何使用运算符重载前,我先说说Delphi里record的新功能。

Delphi2006 里,record已经和class 很类似了,例如

type

TMyRecord = record

private

x : Integer;

public

constructor Create(val : Integer);

procedure Change(arg : integer); overload;

procedure Change(arg1, arg2 : Integer);overload;

end;

record和class的区别是

record 不支持继承

record 包含可变部分;class没有(关于可变部分,请参考Delphi2006的帮助文件)

record 是值类型;class是引用类型(具体的情况,同样请参考Delphi2006的帮助文件)

record 允许在Win32 和 .Net平台都支持运算符重载;class只在.NET里支持

record 是自动构造的,使用的是默认的无参数构造函数,class必须显式构造;由于record拥有默认的无参数构造函数,所以用户定义的构造函数至少要有一个参数

record 没有析构函数

record 不支持虚方法

record 在Win32里不支持interface的实现,在.NET里可以支持

好了,该看看运算符重载是如何实现的了

首先是定义,句法如下:

type

typeName = [class | record] //只有使用.NET时,才能用class

class operator conversionOp(a: type): resultType;

class operator unaryOp(a: type): resultType;

class operator comparisonOp(a: type; b: type): Boolean;

class operator binaryOp(a: type; b: type): resultType;

end;

实现部分的句法如下:

class operator typeName.conversionOp(a: type): resultType;

class operator typeName.unaryOp(a: type): resultType;

class operator typeName.comparisonOp(a: type; b: type): Boolean;

class operator typeName.binaryOp(a: type; b: type): resultType;

还是看看具体的例子吧 :)

type

TVector = record

x : Single;

y : Single;

z : Single;

public

constructor Create(x1, y1, z1); //这个构造函数可以不用写,原因稍后告知

class operator Add(V1, V2 : TVector): TVector; //重载运算符 +

class operator Implicit(i : Single): TVector; overload; //隐式转换

class operator Implicit(i : TVector): TVector; overload; //同上

end;

//具体的实现

{ TVector }

constructor TVector.Create(x1, y1, z1: Single);

begin

x := x1;

y := y1;

z := z1;

end;

class operator TVector.Add(V1, V2: TVector): TVector;

begin

Result.x := v1.x + v2.x;

Result.y := v1.y + v2.y;

Result.z := v1.z + v2.z;

Result.w := v1.w + v2.w;

end;

class operator TVector.Implicit(i: Single): TVector;

begin

Result.x := i;

Result.y := i;

Result.z := i;

Result.w := i;

end;

class operator TVector.Implicit(i: TVector): TVector;

begin

Result.x := i.x;

Result.y := i.y;

Result.z := i.z;

Result.w := i.w;

end;

//调用方法

...

var

v1, v2 : TVector;

begin

...

v1.Create(1, 2, 3);

//也可以用如下的方法给x,y,z赋值

// v1.x := 1;

// v1.y := 2;

// v1.z := 3;

//所以说刚才的Create函数可以不要

//和class不同,record可以自动给成员初始化

//这个例子里,x,y,z的初始化值为 0

v2 := 1; //调用了class operator Implicit(i : TVector): TVector

//这时v2所有成员都被赋值成1

v2 := v1; //调用了class operator Implicit(i : TVector): TVector

v2 := v1 + v2; //调用了class operator Add(V1, V2 : TVector): TVector;

v2 := v2 + 1; // class operator Add(V1, V2 : TVector): TVector

//和class operator Implicit(i : TVector): TVector的复合调用

end;

Delphi的这种实现方式显然比C++要方便,因为你不用考虑内存释放;也可以不用定义构造函数。