Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 2006不允许记录方法中记录类型的常量参数? 更新:简单的解决方法。方法/运算符字段之前的数据字段。_Delphi - Fatal编程技术网

Delphi 2006不允许记录方法中记录类型的常量参数? 更新:简单的解决方法。方法/运算符字段之前的数据字段。

Delphi 2006不允许记录方法中记录类型的常量参数? 更新:简单的解决方法。方法/运算符字段之前的数据字段。,delphi,Delphi,今天我尝试用我能做的最简单的例子来重现这个bug 我从一个基本记录(TBasicRecord)开始,它只有简单的设置和打印方法(没有操作符),并且传递const x:TBasicRecord没有问题 然后,我添加了一个一元运算符,认为这会触发bug,但在将记录作为const传递时仍然没有问题 然后我添加了一个二进制操作符,但是这个bug仍然没有出现 最后,我注意到,在我的简单示例中,我在方法字段之前声明了数据字段,这就是消除bug所需的全部内容 我还将我的数据字段设置为私有,所以起初我认为这

今天我尝试用我能做的最简单的例子来重现这个bug

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

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

  • 然后我添加了一个二进制操作符,但是这个bug仍然没有出现

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

我还将我的数据字段设置为私有,所以起初我认为这一定是个问题,但最终证明这与此无关。唯一不同的是,我是否将数据字段放在运算符和方法字段之前

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


原始发布:

以前我一直在使用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));