1

const と宣言され、ポインターを介してデータを変更するメンバー関数があります。これは誤解を招くようです。const キーワードを削除する必要がありますか?

他の人がコードでこの状況をどのように処理しているか知りたいです。人々は何が起こっているのかを明確にするためにコメントを追加するだけですか? const キーワードをメンバー関数に追加していませんか? たぶん完全に別の何か?

アドバイスをいただければ幸いです。

4

3 に答える 3

3

基本的に2つの選択肢があります。

深い恒常性:

class Foo
{
    T * ptr;
public:
    T       & operator*()       { return *ptr; }
    T const & operator*() const { return *ptr; }
    T       * operator->()       { return ptr; }
    T const * operator->() const { return ptr; }
};

浅い恒常性:

class Foo
{
    T * ptr;
public:
    T & operator*() const { return *ptr; }
    T * operator->() const { return ptr; }
};

それは本当にあなた次第であり、あなたのクラスの目的次第です。クラスがスマートポインターである場合、クラスは可能な限り生のポインターに類似していると想定されるため、浅い定数セマンティクスを持つことが合理的と思われます(もちろん、非定数のポインターへの一定の生のポインターを持つことができます) )。

それ以外の場合は、メンバーポインタオブジェクトへのアクセスを公開する理由を自問する必要があります。クラスへの絶え間ない参照を介して可変アクセスを提供したい場合は確かに可能ですが、それらは特別でまれな状況だと思います。そもそも、コードにそれほど多くの生のポインターが含まれているべきではありません。ポインターを逆参照することによって深く定数の参照を返すことは問題ありませんが、通常は、クラス内にポインターがあるという事実を隠す、より適切にカプセル化された「getter」関数にありますT const & get() const { return *ptr; }

于 2012-09-13T16:41:23.237 に答える
2

一般的に、はい。たとえそれができるとしても、定数を宣言しているものを変更するのは欺瞞的です。

誰かがあなたのコードを使用して const を見た場合、彼らは const を期待しています。変更は、あなたにとっては賢明なことですが、重大な問題を引き起こす可能性があります。プログラムがクラッシュすることさえあります。

于 2012-09-13T16:37:12.473 に答える
0

動的配列を実装するために使用されるstd::vector<Blah>メンバーとメンバーを考えてみましょう。Blah*ほとんどの場合、後者を前者に置き換えるのが理にかなっています。Blah*メンバーを使用すると、メソッドはconst配列内のデータを変更できますが、std::vector<Blah>メンバーを使用すると、constメソッドは配列内のデータを変更できません。

また、要素への割り当てを可能にするプロキシを返すインデックス メソッドを持つマトリックス クラスを考えてみましょう。プロキシを介して割り当てると、プロキシ オブジェクト自体ではなく、マトリックスが変更されます。constしたがって、プロキシ オブジェクトの代入演算子は、主な仕事が物事を変更することである一方で、その効果に可能な限り多くの制約を課すために、することができます (そうあるべきです) 。

これは、設計レベルとコーディング レベルが異なるもう 1 つの例です。

メンバー配列を使用した最初の例ではconst、設計レベルの制約を表現することがすべてでしたが、代入プロキシを使用した 2 番目の例ではconst、コーディング レベルの制約を表現することがすべてでした。

ただし、これらの使用法は互換性がありません。重要なアイデアは、コードの読者にできるだけ多くの制約を提供することです (これにより、コードを理解したり処理したりするために考慮しなければならないさまざまな事柄の数が大幅に減少するため)。const結論:実際にできるところならどこでも追加してください。

于 2012-09-13T17:15:46.733 に答える