gpt4 book ai didi

Delphi 2006 不允许在记录方法中使用记录类型的 const 参数?

转载 作者:行者123 更新时间:2023-12-03 14:50:35 25 4
gpt4 key购买 nike

更新:简单的解决方法。方法/运算符字段之前的数据字段。

今天,我尝试使用我能做的最简单的示例来重现此错误。

  • 我从一个基本记录 (TBasicRecord) 开始,只有简单的设置和打印方法(没有运算符),并且传递 const x:TBasicBecord 没有问题。

  • 然后我添加了一个一元运算符,认为这会触发错误,但将记录作为 const 传递仍然没有问题。

  • 然后我添加了一个二元运算符,但错误仍然没有出现。

  • 最后,我注意到在我的简单示例中,我在方法字段之前声明了数据字段,结果这就是消除 bug 所需的全部内容。

我还将我的数据字段设为私有(private),所以一开始我认为这一定是问题所在,但最终证明这是无关紧要的。唯一有区别的是我是否将数据字段放在运算符和方法字段之前。

总的来说,我对这个决议感到满意。就我个人而言,无论如何我总是把数据字段放在第一位。有趣的是,只要您不尝试将记录类型作为“const”参数传递到任何地方,那么以相反的方式执行似乎不会导致任何其他问题。

<小时/>

原始帖子:

以前我一直使用 Delphi 7,但今天安装了 Delphi 2006,以访问 D7 不支持的运算符方法。

我试图编译对早期问题的回复之一中列出的代码(复数实现):Request simple example of how to a TComplexMath class (source included)

以下是相关代码的部分列表:

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 错误:“----”的声明与先前的声明。 (其中“---”是运算符(operator)名称)。

我的解决方法是从每个 TComplex 参数中删除 const 关键字,然后代码就可以正确遵守(并运行)。我可以保留“const x: Double”参数,编译器不会给出任何错误,但我必须从所有其他参数中删除“const”。

有谁知道这是否是某个未启用的编译器选项?或者 Delphi 的更高版本支持此功能,但 D2006 不支持?或者只是我做错了什么?

另外,如果我不能在这里使用 const 参数,那么用 var 替换 const 是否有任何优势(与完全删除 const 关键字相比)。

最佳答案

您不应该将 const 替换为 var。让我解释一下原因。

背景

function Add(a: integer): integer;
begin
result := a + 5;
end;

返回其参数 + 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

现在您甚至不能执行Add(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) 不会'不工作!!)!

a := 10;
ShowMessage(IntToStr(Add(a))); // You get 15
ShowMessage(IntToStr(a)); // You get 15 (!!!)

那么,什么是const?好吧,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;

甚至无法编译!但您仍然可以执行Add(10)

相关案例

从本次讨论中可以清楚地看出,您不应将 const 替换为 var。确实,

  1. 如果从 const 更改为 var,您的函数将不再接受文字 (10) 或表达式 (标记 + 30SomeFunc(a, b))。 这是一场重大的表演!
  2. 函数的 future 实现可能会更改参数,这会意外更改作为参数传递的变量。

第一点示例。使用 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):

var
a, b, c: TComplex;
begin

a := -(b + c);

确实,现在Negative的参数不是变量,而是表达式b + c。所以你输得很惨!

第二点的示例。假设您今天过得很糟糕,并且您将 Negative 的实现搞砸了

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 code>,这是非常出乎意料的!

结论

因此,您的情况的解决方案就是完全删除 const (而不是用 var 替换它!)。

关于Delphi 2006 不允许在记录方法中使用记录类型的 const 参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15145615/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com