Delphi 2006不允许记录方法中记录类型的常量参数? 更新:简单的解决方法。方法/运算符字段之前的数据字段。
今天我尝试用我能做的最简单的例子来重现这个bugDelphi 2006不允许记录方法中记录类型的常量参数? 更新:简单的解决方法。方法/运算符字段之前的数据字段。,delphi,Delphi,今天我尝试用我能做的最简单的例子来重现这个bug 我从一个基本记录(TBasicRecord)开始,它只有简单的设置和打印方法(没有操作符),并且传递const x:TBasicRecord没有问题 然后,我添加了一个一元运算符,认为这会触发bug,但在将记录作为const传递时仍然没有问题 然后我添加了一个二进制操作符,但是这个bug仍然没有出现 最后,我注意到,在我的简单示例中,我在方法字段之前声明了数据字段,这就是消除bug所需的全部内容 我还将我的数据字段设置为私有,所以起初我认为这
- 我从一个基本记录(TBasicRecord)开始,它只有简单的设置和打印方法(没有操作符),并且传递const x:TBasicRecord没有问题
- 然后,我添加了一个一元运算符,认为这会触发bug,但在将记录作为const传递时仍然没有问题
- 然后我添加了一个二进制操作符,但是这个bug仍然没有出现
- 最后,我注意到,在我的简单示例中,我在方法字段之前声明了数据字段,这就是消除bug所需的全部内容
原始发布: 以前我一直在使用Delphi7,但今天安装了Delphi2006来访问D7不支持的运算符方法 我试图编译对前面问题的一个答复中列出的代码(复数实现): 以下是相关代码的部分列表:
type
TComplex = record
public
class operator Implicit(const D: Double): TComplex;
class operator Negative(const C: TComplex): TComplex;
class operator Equal(const C1, C2: TComplex): Boolean;
class operator NotEqual(const C1, C2: TComplex): Boolean;
class operator Add(const C1, C2: TComplex): TComplex;
class operator Add(const C: TComplex; const D: Double): TComplex;
class operator Add(const D: Double; const C: TComplex): TComplex;
class operator Subtract(const C1, C2: TComplex): TComplex;
class operator Subtract(const C: TComplex; const D: Double): TComplex;
class operator Subtract(const D: Double; const C: TComplex): TComplex;
class operator Multiply(const C1, C2: TComplex): TComplex;
class operator Multiply(const C: TComplex; const D: Double): TComplex;
class operator Multiply(const D: Double; const C: TComplex): TComplex;
class operator Divide(const C1, C2: TComplex): TComplex;
class operator Divide(const C: TComplex; const D: Double): TComplex;
class operator Divide(const D: Double; const C: TComplex): TComplex;
function IsZero: Boolean;
function IsNonZero: Boolean;
function Conj: TComplex;
function Sqr: TComplex;
function Sqrt: TComplex;
function Mag: Double;
function SqrMag: Double;
public
r: Double;
c: Double;
end;
class operator TComplex.Negative(const C: TComplex): TComplex;
begin
Result.r := -C.r;
Result.c := -C.c;
end;
---- etc ---
问题是,当我尝试编译这段代码(在D2006中)时,每一个采用TComplex类型的运算符都会给出一个错误E2037:“---”的声明与前面的声明不同。(其中“---”是操作员名称)
我的解决方法是从每个TComplex参数中删除const关键字,然后代码正确地符合(并运行)。我可以保留“const x:Double”参数,编译器在这些参数上没有给出错误,但我必须从所有其他参数中删除“const”
有人知道这是不是某个未启用的编译器选项吗?或者在Delphi的更高版本中支持这一点,但在D2006中不支持?或者只是我做错了什么
另外,如果我不能在这里使用const参数,那么用var替换const(与完全删除const关键字相比)是否有任何好处。您不应该用var
替换const
。让我解释一下原因
背景
返回其参数+5。尝试ShowMessage(IntToStr(Add(10)))
。你也可以做a:=10;ShowMessage(IntToStr(Add(a)))
以获得相同的结果。在这两种情况下,传递给函数Add
的是数字10
。消息显示15
var
参数的预期用途如下:
procedure Add(var a: integer);
begin
a := a + 5;
end;
var
指示应通过引用传递参数变量;也就是说,只应将指向参数变量的指针传递给过程/函数
因此,现在你可以做了
a := 10;
Add(a);
ShowMessage(IntToStr(a)); // You get 15
现在您甚至不能执行添加(10),因为10
根本不是一个变量
相比之下
function Add(a: integer): integer;
begin
a := a + 5;
result := a;
end;
不会影响a
。所以
a := 10;
ShowMessage(IntToStr(Add(a))); // You get 15
ShowMessage(IntToStr(a)); // You get 10
现在,考虑这个可怕的函数:
function Add(var a: integer): integer;
begin
a := a + 5;
result := a;
end;
这也将返回它的参数+5,但它也会影响它的参数(非常意外!!),并且除了变量之外,你不能传递任何东西作为参数(因此Add(10)
将不起作用!!)
那么,什么是常量?嗯,const
大致意思是“尽可能通过引用传递(以加快速度;例如,您不需要复制一个大记录),但永远不要接受对参数的任何更改”。因此,const
参数有效地作为普通参数工作,除非您不能更改它:
function Add(const a: integer): integer;
begin
result := a + 5;
end;
工作时
function Add(const a: integer): integer;
begin
a := a + 5;
result := a;
end;
甚至不编译!但您仍然可以执行添加(10)
相关案例
从这个讨论中,应该清楚地看到,您不应该用var
替换const
。的确
const
更改为var
,则函数不再接受文本(10
)或表达式(Tag+30
或SomeFunc(a,b)
)的参数这是一个重要的节目停止强>const
或普通参数:
function Complex(a, b: real): TComplex;
begin
result.r := a;
result.c := b;
end;
...
var
c, d: TComplex;
begin
d := -c; // Works!
d := -Complex(10, 20); // Works!
但是使用var
:
var
c, d: TComplex;
begin
d := -c; // Works!
d := -Complex(10, 20); // [DCC Error] Unit5.pas(262):
// E2015 Operator not applicable to this
// operand type
var
a, b, c: TComplex;
begin
a := -(b + c);
这也不起作用(使用var
):
实际上,Negative
的参数不是变量,而是表达式b+c
。所以你输了很多
第二点的例子。说你今天过得不好,你把否定的的实现搞砸了
class operator TComplex.Negative(var C: TComplex): TComplex;
begin
C.r := -C.r;
C.c := -C.c;
result := C;
end;
那么下面的代码,
var
c, d: TComplex;
begin
c := Complex(10, 20);
d := -c;
ShowMessage(FloatToStr(c.r));
ShowMessage(FloatToStr(d.r));
它通常会导致消息10
和-10
,会突然改变并产生-10
,-10
,这是非常出乎意料的
结论
因此,在您的情况下,解决方案就是完全删除const
(不要用var
!)替换它。在运算符重载中不要用var替换const。句号
即使您承诺永远不会在函数体中修改var参数(这是一个可疑的基础),只要var参数的存在就会破坏运算符函数的一个非常重要的方面:表达式的组合。运算符函数中的var参数使该运算符无法与compo中的其他运算符组合在一起
class operator TComplex.Negative(var C: TComplex): TComplex;
begin
C.r := -C.r;
C.c := -C.c;
result := C;
end;
var
c, d: TComplex;
begin
c := Complex(10, 20);
d := -c;
ShowMessage(FloatToStr(c.r));
ShowMessage(FloatToStr(d.r));