游戏开发论坛

 找回密码
 立即注册
搜索
查看: 7772|回复: 11

使用Delphi编游戏者的福音--关于运算符重载

[复制链接]

27

主题

418

帖子

455

积分

中级会员

Rank: 3Rank: 3

积分
455
QQ
发表于 2007-3-13 23:31:00 | 显示全部楼层 |阅读模式
使用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++要方便,因为你不用考虑内存释放;也可以不用定义构造函数。


好了,就到这里了。
欢迎交流,无论你是否使用Delphi。



附件是演示程序。













sf_200731323315.rar

156.59 KB, 下载次数:

2万

主题

2万

帖子

6万

积分

论坛元老

Rank: 8Rank: 8

积分
66489
QQ
发表于 2007-3-14 00:04:00 | 显示全部楼层

Re:使用Delphi编游戏者的福音--关于运算符重载

Delphi for Win32已经2007了
另外Borland C++ Builder/Turbo C++开始用字母代替操作符了

比如 if( (a == 0 and b==0) or (a == 1 )) 之类已经出现了。

197

主题

1041

帖子

1104

积分

金牌会员

Rank: 6Rank: 6

积分
1104
QQ
发表于 2007-3-14 09:46:00 | 显示全部楼层

Re:使用Delphi编游戏者的福音--关于运算符重载

我是古典pascal。我用fpc

62

主题

331

帖子

366

积分

中级会员

Rank: 3Rank: 3

积分
366
QQ
发表于 2007-3-14 10:40:00 | 显示全部楼层

Re:使用Delphi编游戏者的福音--关于运算符重载

这个,貌似2007要登场了吖

..
Delphi® 2007 for Win32®   

The RAD visual development environment for Windows®

Revitalize Win32 development by creating native code applications compatible with Windows 2000, XP, and Vista™
Embrace Web 2.0 technologies with Delphi’s new support for AJAX
New DBX4 database architecture streamlines database connectivity and supports the latest versions of SQL databases
Simplify management of even the most complex projects with MSBuild’s powerful project build/make support


62

主题

331

帖子

366

积分

中级会员

Rank: 3Rank: 3

积分
366
QQ
发表于 2007-3-14 10:41:00 | 显示全部楼层

Re:使用Delphi编游戏者的福音--关于运算符重载

delphi for php不知道哪个玩过吖

..

8

主题

716

帖子

716

积分

高级会员

Rank: 4

积分
716
发表于 2007-3-14 16:07:00 | 显示全部楼层

Re:使用Delphi编游戏者的福音--关于运算符重载

函数重载只是为了好看而已
一些条件下还会带来不必要的值拷贝开销
优化的结果依赖于编译器的智能程度

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
发表于 2007-3-14 18:01:00 | 显示全部楼层

Re:使用Delphi编游戏者的福音--关于运算符重载

真素激动挖,好久没看到善人袅........
激动得偶滴心是挖拉挖拉挖拉的....

27

主题

418

帖子

455

积分

中级会员

Rank: 3Rank: 3

积分
455
QQ
 楼主| 发表于 2007-3-15 11:54:00 | 显示全部楼层

Re: Re:使用Delphi编游戏者的福音--关于运算符重载

hyzboy: Re:使用Delphi编游戏者的福音--关于运算符重载

Delphi for Win32已经2007了
另外Borland C++ Builder/Turbo C++开始用字母代替操作符了

比如 if( (a =...


你说的用字母代替操作符,其实是向Delphi学习!
Delphi写出来就是下面的样子
if ((a = 0) and (b = 0) or (a = 1)) then
begin
...
end;

27

主题

418

帖子

455

积分

中级会员

Rank: 3Rank: 3

积分
455
QQ
 楼主| 发表于 2007-3-15 11:59:00 | 显示全部楼层

Re:使用Delphi编游戏者的福音--关于运算符重载

各位为什么说Delphi2007要出来了呢?
我说的运算符重载Delphi2006和TurboDelphi就能支持

27

主题

418

帖子

455

积分

中级会员

Rank: 3Rank: 3

积分
455
QQ
 楼主| 发表于 2007-3-15 12:08:00 | 显示全部楼层

Re: Re:使用Delphi编游戏者的福音--关于运算符重载

千里马肝: Re:使用Delphi编游戏者的福音--关于运算符重载

函数重载只是为了好看而已
一些条件下还会带来不必要的值拷贝开销
优化的结果依赖于编译器的智能程度


不只是好看,更多的是方便。同样是个TVector类,要实现两个向量相加
以前的Delphi
V3 := VectorAdd(V1, V2);
Delphi2006
V3 := V1 + V2;


当然性能损失肯定有,但是现在都用高级语言,难道为了性能,都去用Asm或机器语言吗?
为了更易于理解,更方便的编码,少许的性能损失是可以接受的。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-26 17:59

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表