Delphi 2006不允许在记录方法中使用type记录的const参数吗? [英] Delphi 2006 wont allow const parameters of type record within record method?

查看:50
本文介绍了Delphi 2006不允许在记录方法中使用type记录的const参数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Today I tried to reproduce this bug using the simplest example I could make.


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

  • I started with a basic record (TBasicRecord) having only simple set and print methods (no operators), and there was no problem passing const x:TBasicBecord.

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

I then added a unary operator thinking that would trigger the bug, but still no problems in passing the record as const.

然后我添加了一个二进制运算符,但仍然不会出现该错误。

I then added a binary operator, but and still the bug wouldn't surface.

最后,在我举过的简单示例中我注意到数据字段位于方法字段之前,而事实证明,这是消除bug所需的全部条件。

Finally I noticed in my simple example I had declared the data fields ahead of the method fields, and this turned out to be all that's required to mute the bug.

我也将数据字段设为私有,所以起初我以为一定是问题所在,但最终却无关紧要。唯一不同的是我是否将数据字段放在运算符和方法字段之前。

I'd also made my data fields private, so at first I thought that must be the issue, but in the end it turned out to be irrelevant. The only thing that makes a difference is whether of not I placed the data fields before the operator and method fields.

总的来说,我对这种分辨率感到满意。就我个人而言,无论如何我总是将数据字段放在首位。有趣的是,只要您不尝试在任何地方将记录类型作为 const参数传递,相反的做法似乎不会引起任何其他问题。

Overall I'm happy with this resolution. Personally I've always put the data fields first anyway. It's funny that doing it the other way around didn't seem to cause any other problems, just as long as you don't try to pass the record type as a "const" parameter anywhere.

原始发布:

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

Previously I have been using Delphi 7 but today installed Delphi 2006 to gain access to operator methods that D7 didn't support.

我正在尝试编译其中一份答复中列出的代码(复数实现)。到此处的先前问题:请求有关如何执行TComplexMath类的简单示例(包括源代码)

I was attempting to compile the code (complex number implementation) listed in one of the replies to an earlier question here: Request simple example of how to a TComplexMath class (source included)

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

Here's a partial listing of the relevant code:

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的错误: ----的声明不同于先前的声明。 (其中-是操作员名称)。

The problem is, when I try to compile this code (in D2006), every operator that takes a TComplex type gives an error of E2037: Declaration of "----" differs from the previous declaration. (where "---" is the operator name).

我的解决方法是从每个TComplex参数中删除 const 关键字,然后代码正确地执行(并运行)。我可以保留 const x:Double参数,编译器对此没有错误,但是我必须从所有其他参数中删除 const。

My work around was to just remove the const keyword from every TComplex parameter and then the code complies (and runs) correctly. I can keep the "const x: Double" parameters,the compiler gives no error on those, but I had to remove "const" from all of the others.

可以有人知道这是否是未启用的某些编译器选项吗?还是更高版本的Delphi中支持此功能,但D2006不支持?还是只是我做错了其他事情?

Does anyone know if this is some compiler option that's not enabled? Or is this something supported in later versions of Delphi but not D2006? Or just me doing something else incorrectly?

此外,如果我在这里不能使用const参数,只用 var 代替会有什么好处吗? const (与完全删除const关键字相比)。

Also, if I cant use const parameters here, would there be any advantage to just substituting var for const (compared to just deleting the const keyword altogether).

推荐答案

您不应该 var 替换 const 。让我解释为什么。

You should not replace const by var. Let me explain why.

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

返回其参数+5。尝试 ShowMessage(IntToStr(Add(10) ))。您也可以执行 a:= 10; ShowMessage(IntToStr(Add(a)))获得相同的结果。在这两种情况下,传递给函数 Add 的东西都是数字 10 。消息显示 15

returns its argument + 5. Try ShowMessage(IntToStr(Add(10))). You can also do a := 10; ShowMessage(IntToStr(Add(a))) to get the same result. In both cases, the thing passed to the function Add is the number 10.The message shows 15.

var 参数的预期用法如下:

The intended use of var parameters is like this:

procedure Add(var a: integer);
begin
  a := a + 5;
end;

var 表示参数变量应为通过引用传递;也就是说,仅应将指向变量的指针传递给过程/函数。

var indicates that the argument variable should be passed by reference; that is, only a pointer to the argument variable should be passed to the procedure/function.

因此,现在您可以这样做

Hence, now you can do

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

现在您无法甚至可以执行 Add(10),因为 10 根本不是变量!

Now you cannot even do Add(10), since 10 isn't a variable at all!

进行比较,

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   

现在,考虑一下这个可怕的功能:

Now, consider this horrible function:

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

这还将返回其参数+ 5,但也会影响其参数(非常不正确! ),并且除了变量以外,您什么都不能作为参数传递(因此 Add(10)无效!)!

This will also return its argument + 5, but it will also affect its argument (very unexpextedly!!), and you cannot pass anything but variables as arguments (so Add(10) won't work!!)!

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

那么,什么是 const ?好吧, const 大致意思是如果可能,通过引用传递(以加快速度;例如,您无需复制大型记录),但不要接受任何更改争论。因此, const 参数实际上可以像普通参数一样工作,除了您不能更改它之外:

So, what is const? Well, const roughly means "pass by reference if possible (to speed up; for instance, you need not make a copy of a large record), but do never accept any changes to the argument". Hence, a const argument effectively works as normal argument except that you cannot change it:

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)

doesn't even compile! But you can still do Add(10).

从本次讨论中应该清楚,您不应该将 const 替换为 var 。确实,

From this discussion, it should be clear that you shouldn't replace const by var. Indeed,


  1. 如果您从 const 更改为 var ,您的函数不再接受文字( 10 )或表达式( Tag + 30 SomeFunc(a,b))。 这是一个主要的显示停止器!

  2. 该函数的未来实现可能会更改参数,这将不小心更改作为参数传递的变量。

  1. If you change from const to var, your functions no longer accept arguments that are literals (10) or expressions (Tag + 30 or SomeFunc(a, b)). This is a major show-stopper!
  2. Future implementations of the functions might change the arguments, which will accidently change the variables passed as arguments.

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

This will not work either (with var):

var
  a, b, c: TComplex;
begin

  a := -(b + c);

实际上,现在 Negative 的论点是不是变量,而是表达式 b + c 。因此,您损失惨重!

Indeed, now the argument of Negative isn't a variable, but the expression b + c. So you lose very much!

第二点的例子。假设您今天过得很糟糕,并且弄巧了负到

Example of second point. Say you have a bad day and you suckify the implementation of Negative to

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

which used to result in messages 10 and -10, will suddenly change and yield -10, -10, which is highly unexpected!

因此,您的解决方案只是完全删除 const (而不用 var 代替!)。

The solution in your case, therefore, is simply to remove const altogether (and NOT replace it by var!).

这篇关于Delphi 2006不允许在记录方法中使用type记录的const参数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆