0

この非常に単純なコードを見てください。

struct A { char* s; };

class B
{
    A* a;

    public: B(const char* s) : a(new A()) {
        int len = strlen(s);
        a->s = new char[len + 1];
        memcpy(a->s, s, len + 1);
    }

    ~B() { delete [] a->s; delete a; }

    const char* c_str() const { return a->s; }

    const B& to_upper() const {
        char* x = a->s;
        int len = strlen(x);
        for (int i = 0; i < len; i++)
        {
            char k = x[i];
            if (k >= 'a' && k <= 'z')
                x[i] -= 32;
        }
        a->say_hi();
        return *this;
    }
};

int main() {
    B b = "hola mundo";
    printf("%s\n", b.to_upper().c_str());
}

できます!!私の質問は...なぜですか?

to_upper()メソッドはconstであり、値のpointeeを「a」で変更します。わかりました。「a=nullptr;」のようなことはできません。コンパイラが次のように言っているからです。「読み取り専用オブジェクトを変更しようとしています」。ただし、基になる値を変更できます。この動作は正しいですか?constメソッドで"this"の型が"constB *"に変換されるのと同じ方法で、"a"型を"const A *"に変換するべきではありませんか?

ありがとう!

4

2 に答える 2

6

メソッドのconstnessは、オブジェクトのconstnessに変換されます。つまり、ポインターの*this内部にはタイプがあります。これですべてです。これ以上でもそれ以下でもありません。この効果は、たとえばC言語で見られるものと同じです。ポインタをconstにしますが、ポインタには影響しません。to_upperthisconst B *this->a

実際、の定数がで指定されたオブジェクトにB伝播するかどうかを決定するのはあなた次第です。言語はあなたにこの決定をする際の完全な自由を与えます。これは「概念的恒常性」と呼ばれます(「物理的恒常性」または「論理的恒常性」とは対照的です)。コンパイラーは論理的恒常性のみを監視および実施しますが、OOPのキーワードの目的はそれをはるかに超えています。つまり、概念的恒常性の概念を設計に実装できます。Athis->aconst

Aオブジェクトがの不可欠な部分であると見なされる場合、BのconstnessBは。のconstnessも意味する必要がありAます。しかし、これは手動で監視および実施する必要があるものです(または、スマートポインタークラスがこれを支援します)。

オブジェクトがたまたまから参照Aされているだけの独立したオブジェクトである場合、のconstnessは必ずしも。のconstnessを意味する必要はありません。BBA

コンパイラーは、実装しようとしているオブジェクトの関係を認識していないため、これに関してユーザーに決定を課すことはありません。あなたのデザインでは、私が見ているように、Aオブジェクトは実際にはの不可欠な部分ですB。つまり、あなたが自分to_upperをとして宣言することは想定されていませんでしたconst。変更機能です。これは、ユーザーが.の値として認識するものを変更しますB。あなたが本質的にユーザーに「嘘をついている」と宣言to_upperすることによって。const

于 2012-07-02T03:30:49.857 に答える
1

const関数は、クラスメンバーを変更してはなりません。'pointeebya'はクラスのメンバーではありません。

于 2012-07-02T03:26:18.647 に答える