4

この問題を小さな代表的なサンプルに要約しました。

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ですか? ここで何かひどく間違ったことをしているような気がします。

4

3 に答える 3

5
const Foo getFoo()

と同じです

Foo getFoo() const

不可視のthisパラメータになりますconst。はDで推移的であるためconst、からメンバー変数を返そうとするとthis、それconstも同様になります。値型の場合fooは、それをコピーするだけで、Foo元の値に影響を与えないため、ミュータブルを返すことは問題になりません。ただしFoo、はクラスであるため、参照型です。したがって、returningfooは、保持しているのとまったく同じオブジェクトへの参照を返しStateます。コピーは作成されません。そして、それはそうであるに違いありません-そうでなけれconst、パラメータの恒常性に違反することになりthisます。

いいえ、捨てることconstは良い解決策ではありません。この質問で説明したように、Dでは、値をキャストしてからconst変更することは事実上違法です。これを行うと、型システムに違反することになります。コンパイラーはあなたにそれをさせます、しかしあなたがそうするときあなたがあなた自身の手にあなたの人生を取っているならば。基になるオブジェクトが実際immutableにある場合は特に悪いです。その場合、セグメンテーション違反が発生する可能性があるためです。どうしてもやらなければならない場合にのみキャストしconst、自分が何をしているのかを本当に理解していない限り、それを変更することはありません。

いいえ、正しい解決策はリターンタイプを作成することですconst

const(Foo) getFoo() const

これで、戻っfooて使用できます。ミュータブルが必要な場合は、であるFoo必要はないかgetFoo、のコピーを返すconst必要があります。例えばgetFoofoo

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;
}

ここから取り除く重要なことはconst、Dでは推移的であるということです。ウォルター・ブライトが言うように、「それはずっとカメです」。何かができたらconstそのすべての部分がありconst、自分が何をしているのかを本当に理解していない限り、それを回避するために捨てないでください。したがって、関数からメンバー変数を参照する参照型を返す場合は、戻り型を作成するか、そのコピーを作成してそれを返す必要があります。constconstconst

于 2012-04-29T01:24:23.183 に答える
4

あなたが本当に欲しいのはこれだと思います:

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;
    }
}
于 2012-04-29T02:10:55.010 に答える
3

const(Foo)メソッドのシグネチャが であるため、メンバーは として解釈されます。これは、変更できないことconst Foo getFoo()を意味します。foo

を削除するconstと、問題ないはずです。

于 2012-04-28T15:22:35.007 に答える