Properties D:常量正确性-我做错了什么?
我目前正在实现一个基于二叉树的数据结构。作为其中的一部分,我有(为了便于测试,目前是公共的)实例变量Properties D:常量正确性-我做错了什么?,properties,constants,d,Properties,Constants,D,我目前正在实现一个基于二叉树的数据结构。作为其中的一部分,我有(为了便于测试,目前是公共的)实例变量left和right作为创建结构时使用的每个节点对象的一部分。我希望能够快速访问sub,这是使用以下功能完成的: @property Node sub() in { assert(!isLeaf); } body { return (val != left.val) ? left : right; } 这里提到的所有东西都是公开的
left
和right
作为创建结构时使用的每个节点
对象的一部分。我希望能够快速访问sub,这是使用以下功能完成的:
@property Node sub()
in {
assert(!isLeaf);
}
body {
return (val != left.val) ? left : right;
}
这里提到的所有东西都是公开的。现在,我尝试在契约中使用这个属性函数(特别是out
块,函数的结果绑定到result
)。然而,当我这样做时,编译器抱怨我正在使用constresult
对象调用一个可变方法。但是,当我将sub
的签名更改为@property const Node sub()
时,却出现了以下编译器错误:
错误:无法将const(Node)类型的表达式(this.val!=this.left.val?this.left:this.right)隐式转换为tournament2.Node
我错过了什么?如何解决此问题?最初的问题源于契约无法修改其所属对象的限制(否则,程序在调试和发布模式下的行为可能会有所不同)。语言强制执行该限制的方式是使
this
指针const
const this
意味着您不能修改this
对象的字段,至于调用方法,这些方法本身必须注释为const
,这些方法的代码也受到同样的限制。这解释了第一个错误:合约是const
,试图调用非const
(可变)方法。由于允许可变方法修改此
,并且禁止契约这样做,因此编译器禁止调用
由于D的常量的可传递性,通过这个
指针访问的所有内容都变成常量
。而且,如果任何类字段都是引用类型,那么它们的间接目标也将成为const
。这就是类型系统将禁止修改通过This
指针可以访问的任何内容的方式
这意味着,如果const
方法试图返回一个类字段(带有间接项,例如节点
之类的类类型),则返回的类型也必须是const
。这是第二条错误消息的来源:返回表达式试图将通过常量This
获得的常量节点
值转换为可变的节点
。目前,语法@property const Node sub()
表示方法本身是const
(并且具有asconst this
),而不是返回类型
现在,一般来说,C++中,一个具有适当的常态性支持的对象通常会有多个重载,返回类字段的方法:<代码> const ,以及非->代码> const 。
const
版本将返回const
引用;非常量
将返回非常量
引用。当我们有权访问可变对象时,需要这两个版本来允许获取可变字段引用,但如果我们只有对对象的const
访问权,则仍然允许获取const
引用。大多数情况下,这两个方法的代码是相同的——只有函数签名不同
这就是D的inout
的作用。在方法及其某些参数或返回值上指定它意味着这些参数或返回值将具有与this
(所引用的对象)相同的常量。对于返回的const
和可变值使用相同代码的简单情况,这避免了代码重复
我使用的语法是
@property inout(Node)sub()inout
。我认为它可以用多种方式编写,但这种语法是明确的。这里,在<代码> IONT(NoCub)< /C>中的父母们明确地指出,我们在返回值上应用属性,而不是在函数上应用方法,并且在参数列表之后放置方法(<代码> < <代码> > <代码> IUDUMENT/COD>属性,如C++中的代码> const < /Cord>。明确指定它应用于函数本身。尝试将签名更改为@property inout(Node)sub()inout
@CyberShadow:这就解决了问题,谢谢!你能给我描述一下为什么会这样吗?我想了解问题的根源,这样我以后就不会被这个问题绊倒了。