Koz*_*oss 6 d const properties
我目前正在实现基于二叉树的数据结构.作为其中的一部分,我(当前公开,为了更容易测试)实例变量,left并right作为Node创建我的结构中使用的每个对象的一部分.我希望能够快速访问的一件事是sub,使用此函数完成:
@property Node sub()
in {
assert(!isLeaf);
}
body {
return (val != left.val) ? left : right;
}
Run Code Online (Sandbox Code Playgroud)
这指的所有内容都是公开的.现在,我尝试在契约中使用此属性函数(特别是out块,函数绑定的结果result).但是,当我这样做时,编译器抱怨我正在使用const result对象调用一个可变方法.当我改变的签名sub是@property const Node sub(),但是,我得到这个编译器错误,而不是:
Error: cannot implicitly convert expression (this.val != this.left.val ? this.left : this.right) of type const(Node) to tournament2.Node
我在这里错过了什么?我该如何解决这个问题?
最初的问题源于合同无法修改其所属对象的限制(否则,程序在调试和发布模式下的行为可能会有所不同).语言强制执行该限制的方式是通过制作this指针const.
一种const this方法是您不能修改this对象的字段,并且对于调用方法 - 这些方法本身必须注释为const,并且相同的限制适用于这些方法的代码.这解释了第一个错误:合同,它const试图调用非const(可变)方法.由于允许修改可变方法this,并且禁止合同执行此操作,因此编译器禁止调用.
由于D的常数的传递性,通过this指针访问的所有东西都变成了const.并且,如果任何类字段是引用类型,则它们的间接目标也变为const.这就是类型系统将禁止修改通过this指针可以到达的任何内容的方式.
这意味着如果一个const方法试图返回一个类字段(具有间接性,如类类型Node),则返回的类型也必须如此const.这是第二条错误消息的来源:返回表达式试图将const Node通过它获得的值转换const this为可变的值Node.目前,语法@property const Node sub()表明方法本身是const(并具有as const this),而不是返回类型.
现在,通常,在C++中,具有适当const支持的对象通常会为返回类字段的方法提供多个重载:const和非const.该const版本将返回一个const参考; non const将返回非const引用.当我们有权访问可变对象时,需要两个版本来允许获取可变字段引用,但const如果我们只能const访问该对象,则仍然允许获取引用.大多数情况下,两种方法的代码是相同的 - 只有函数签名才会有所不同.
这就是D'的inout用武之地.在方法及其一些参数或返回值上指定它意味着那些参数或返回值将具有与this(被引用的对象)相同的常量.这避免了返回const和可变值使用相同代码的简单情况下的代码重复.
我使用的语法是@property inout(Node) sub() inout.我认为它可以用多种方式编写,但这种语法是明确的.这里,在括号inout(Node)使其明确我们应用的返回值的属性,而不是功能,并把该方法(this)inout属性参数列表之后,就像const在C++中,unambigously规定,它适用于函数本身.