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

2023-12-28

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

今天我尝试使用我能做的最简单的例子来重现这个错误。

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

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

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

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

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

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


原帖:

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

我试图编译对早期问题的答复之一中列出的代码(复数实现):请求如何使用 TComplexMath 类的简单示例(包含源代码) https://stackoverflow.com/questions/15074316/request-simple-example-of-how-to-a-tcomplexmath-class-source-included/15074443#15074443

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

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 中)时,every采用 TComplex 类型的运算符给出 E2037 错误:“----”的声明与先前的声明不同。 (其中“---”是操作员名称)。

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

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

另外,如果我不能在这里使用 const 参数,那么仅替换会有什么优势吗?var for const(与完全删除 const 关键字相比)。


你应该not代替const by 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

Now you cannot甚至Add(10), since 10根本不是变量!

比较,

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

不会影响a. So,

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? Well, 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 by var。的确,

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

第一点的例子。 Using 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 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 and -10,会突然改变并屈服-10, -10,这是非常出乎意料的!

结论

因此,您的情况的解决方案就是简单地删除const完全(并且不将其替换为var!).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 如何使用 VCL 类的接口 - 第 2 部分 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 继续我之前关于使用 VCL 接口的调
  • 如何处理第三方库中的警告/提示?

    我们使用 FastReport 来生成报告 事实上 我们为访问源代码付费 我们目前使用的是FastReport的最新稳定版本 虽然它对于我们的生产来说足够稳定 但每当我编译时 我都会看到以下内容 dcc32 Hint fs iinirtti
  • 使用 gmail 和 Indy 发送电子邮件

    我正在尝试使用 gmail 从 Delphi 发送电子邮件 我有 Indy 10 5 9 0 和 Delphi XE3 我从以下位置获得了示例代码 http www andrecelestino com delphi xe envio de
  • 如何解决内存分段并强制FastMM释放内存给OS?

    注意 32 位应用程序不计划迁移到 64 位 我正在使用一个非常消耗内存的应用程序 并且几乎优化了与内存分配 取消分配相关的所有相关路径 应用程序本身没有内存泄漏 没有句柄泄漏 没有任何其他类型的泄漏 据我所知并经过测试 我无法触及的第 3
  • Delphi - 如何将通用参数传递给接受 const 参数数组的函数

    我有一个 基类 其中包含一个 函数 该函数接受 const 数组 类型的参数 如下所示 type TBaseClass class TObject public procedure NotifyAll const AParams array
  • Delphi RTTI,已发布的属性出现两次

    我想对属性使用属性 但这些属性偶尔会在继承的类中发生更改 这是一个示例代码 非常简化 TBaseClass class TObject private FFoo string published BaseAttirib hello prop
  • 如何更改 Delphi 2010 IDE 中编辑器选项卡的字体大小?

    有谁知道如何更改 Delphi 2010 IDE 中编辑器选项卡的字体大小 我的 1080p 22 显示器的字体太小 无法阅读 而且会导致眼睛疼痛 一些笔记 它不尊重系统的 DPI 设置 因此更改系统设置没有帮助 而且 我现在已经使用 14
  • Delphi 7,加载PNG到TImage

    只是想加载 PNG 尝试使用适用于其他格式的 OleGraphic 来使用我的 LoadPic 但在 PNG 上失败 目标是将图像复制到隐藏位图 然后将其屏蔽并复制到可见的工作图像画布 如果 CopyRect 不这样做 请随意提出其他建议
  • Delphi (Indy) TIdTCPClient 在线程中

    在互联网上 我看到通常将 TIdTCPClient 放置在自定义 TThread 后代中 为什么要这样做 有时我也在这样的线程中看到服务器 为什么 干杯 阿德里安 Indy 使用阻塞 I O 最好在线程中处理 这是 Indy 整体设计的核心
  • 如何将我的图标添加到组件选项板页面中的组件? [复制]

    这个问题在这里已经有答案了 可能的重复 Delphi非可视化组件图像 https stackoverflow com questions 3319276 delphi non visual component image 如何将我的图标添加
  • 使用普通画布/文本输出更新LayeredWindow

    有没有一种方法可以使用画布在表单上绘图 然后使用 updatelayeredwindow 这样表单就不可见 但文本可见 就像只显示文本的半透明表单一样 如果没有 那么有没有办法只用画布 opengl directx 制作某种半透明形式 我想
  • 如何在 OSX 上的应用程序名称下创建子项菜单?

    如何在下面添加TMenuItemProject1以上Quit在下面的屏幕截图上 我创建了一个 TMenuBar 并选中了 UseOSMenu 属性 我添加的第一个 TMenuItem 是主栏中的第二个 TMenuItem 您可以通过将 II
  • 如何在Delphi XE中通过名称获取类类型引用?

    我实际上正在尝试使用 Rtti 来实现通用方法调用程序 它应该像这样工作 我将提供类名 方法名和参数 调用者将通过调用此类的指定方法来完成其工作 因此 我需要类引用才能获取其 Rtti 信息并寻找我想要调用的方法 有没有办法在不实现我想要使
  • 如何仅在调试模式下激活 ReportMemoryLeaksOnShutdown?

    我需要激活ReportMemoryLeaksOnShutdown报告应用程序内存泄漏的功能 但仅限于调试模式 当 Delphi IDE 运行时 我怎样才能做到这一点 如果您的意思是使用调试构建配置 D2007 编译的 调试模式 则您将定义
  • 如何在滚动框上创建缓慢的滚动效果?

    我喜欢在滚动框中平移图像后创建平滑的减慢滚动效果 就像平移地图一样谷歌地图 http maps google com 我不确定它是什么类型 但行为完全相同 当快速移动地图时 当您释放鼠标时它不会立即停止 而是开始减慢速度 有什么想法 组件
  • 运行delphi客户端自动化程序后excel.exe保持加载状态的原因是什么?

    我编写了一个 Delphi 程序 该程序从单个 XLS 文件的多个不同电子表格中提取数据并将其合并到文本文件中以供以后处理 这是德尔福7console程序 最相关的代码片段的摘录将向您表明 显然 我的程序表现得相当好 或者至少达到了它需要的
  • 我如何在Delphi中处理事件?

    例如 我有一个程序 在单击 Button1 后执行某些操作 如果没有 Button1Click 中的代码 如何处理按钮的 onclick 事件 我需要为 Button1 动态添加事件 unit Unit1 interface uses Wi
  • 如何遍历任意给定集合中的枚举?

    我有很多枚举类型 它们与相应的集合相结合 例如 type TMyEnum meOne meTwo meThree TMyEnums set of TMyEnum 我正在尝试提出一组可以运行的函数any枚举集 而不是为每个枚举编写单独的函数
  • Delphi 2009 IDE结构视图折叠功能

    现在有谁知道折叠 Delphi 2009 IDE 结构视图中的所有项目吗 我不知道折叠所有项目 这使我很难从视图中找到我的课程 Thanks 选择根节点 类 并按数字键盘上的 除号 那会让一切崩溃 然后按数字键盘上的 加号 键 第一级将展开
  • 每次 TDbGrid 的选定位置更改时都会触发什么事件?

    我的项目中有一个 TDbGrid 每次更改所选行时我都试图触发一个事件 行中的任何更改都已经更新了链接到同一数据源的所有数据感知控件 但还需要进行其他更改 我需要一个事件处理程序 我认为 OnColEnter 会起作用 根据帮助文件 它在以

随机推荐