【问题标题】:Why do I have to cast this?为什么我必须投这个?
【发布时间】:2012-04-30 09:49:18
【问题描述】:

我已将这个问题浓缩为一个小的代表性样本:

import std.stdio;

class Foo
{
    private int f;
}

class State
{
    private Foo foo;
    const Foo getFoo()
    {
        return foo; // This line here.
    }
}

void main()
{
    auto s = new State;
    writeln(s.getFoo());
}

我把那个代码放在test.d

$ gdmd test.d
test.d:13: Error: cannot implicitly convert expression (this.foo) of type const(Foo) to test.Foo

我知道它告诉我用cast(test.Foo)foo 转换返回值,但为什么呢?为什么它将成员解释为const(Foo) 类型,为什么需要我抛弃const?我觉得我在这里做错了什么。

【问题讨论】:

    标签: d


    【解决方案1】:
    const Foo getFoo()
    

    一样
    Foo getFoo() const
    

    它使this 参数const 不可见。因为const 在D 中是可传递的,这意味着当您尝试从this 返回成员变量时,它也将是const。如果foo 是一个值类型,那么它只会复制它,然后返回一个可变的Foo 不会有问题,因为它不会影响原始值。但是Foo 是一个类,因此是一个引用类型。因此,返回 foo 是返回对 State 持有的完全相同的对象的引用。没有复制。所以它必须const - 否则你会违反this参数的常量。

    不,抛弃const 不是一个好的解决方案。正如this question 中所讨论的,抛弃const 然后改变值在D 中实际上是非法的。当你这样做时,你违反了类型系统。编译器会让你这样做,但如果你在这样做时将自己的生活掌握在自己手中。如果底层对象实际上是immutable,则尤其糟糕,因为在这种情况下您可能会遇到段错误。只有在万不得已的情况下,您才会抛弃 const,并且您永远不会改变它,除非您真的知道自己在做什么。

    不,正确的解决方法是让返回类型const

    const(Foo) getFoo() const
    

    现在,您可以返回 foo 并使用它。如果你想要一个可变的Foo,那么你要么不必让getFoo 成为const,要么必须让getFoo 返回foo 的副本。例如

    Foo getFoo() const
    {
        //This would be cleaner if you provided a clone/dup function
        //of some kind on Foo.
        auto retval = new Foo;
        retval.f = foo.f;
    
        return retval;
    }
    

    您要从这里得到的重要一点是,D 中的const可传递的。正如沃尔特·布莱特(Walter Bright)所说,“从头到尾都是乌龟。”一旦某个东西是const所有部分都是const,并且不要抛弃const来绕过它,除非你真的 知道你在做什么。所以,如果你想返回一个引用类型,它引用来自 const 函数的成员变量,你要么需要将返回类型设为 const,要么创建它的副本并返回它。

    【讨论】:

    • 万岁,我现在明白多了。
    【解决方案2】:

    我怀疑你真正想要的是这个:

    class State
    {
        private Foo foo;
    
        // When `this` is const, return const(Foo).
        // When `this` is immutable, return immutable(Foo).
        // When `this` is mutable, return Foo.
        inout(Foo) getFoo() inout
        {
            return foo;
        }
    }
    

    相当于:

    class State
    {
        private Foo foo;
    
        Foo getFoo()
        {
            return foo;
        }
    
        const(Foo) getFoo() const
        {
            // `this.foo` is of type const(Foo), as const is transitive.
            return foo;
        }
    
        immutable(Foo) getFoo() immutable
        {
            // `this.foo` is of type immutable(Foo), as immutable is transitive.
            return foo;
        }
    }
    

    【讨论】:

      【解决方案3】:

      它将成员解释为const(Foo),因为您的方法签名是const Foo getFoo(),这意味着foo 不会是可变的。

      去掉const应该没问题。

      【讨论】:

      • 关键是要有一个 const 访问函数,这样其他人可以看到但不能修改数据。是否只是假设因为它是返回为 const 的函数的返回语句?我本来希望它希望我将它转换为 to const,而不是 from const 在这种情况下。
      • 那么你应该将getter声明为Foo getFoo() constA similar question here
      • @Alexander:我这样做时遇到了同样的问题,我无法很好地解读语言规范以说明它的含义。
      • @nmichaels:修复它的更好方法实际上可能是说 const(Foo) 而不是 Foo,因为 D 将第一个 const 解释为引用该方法。
      • @nmichaels const 是瞬态的,所以 (cast(const)s).foo 也将是 const 我认为唯一的方法是const(Foo) getFoo() const
      猜你喜欢
      • 1970-01-01
      • 2011-12-30
      • 1970-01-01
      • 2020-05-13
      • 2013-04-20
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 2011-09-03
      相关资源
      最近更新 更多