8

私はメンバー変数を使用しており、プログラムのある時点でそれを変更したいのですが、意図しない変更を防ぐために他の場所で「ロック」することを好みます。

説明するコード:

class myClass {
    int x;  // This should be prevented to being changed most of the time
    int y;  // Regular variable
    myclass() {x = 1;}
    void foo1 () {x++; y++;} // This can change x
    void foo2 () {x--; y--;} // This shouldn't be able to change x
                             // I want it to throw a compile error
};

問題は、それを何らかの方法で達成できるかどうかです。永続的な const_cast のようなものですか?

コンストラクターの初期化リストと定数をすぐに使用できることはわかっていますが、後で変数を変更する必要があります。

4

7 に答える 7

2

さて、私が嫌いな他のすべての答えなので、ここに私の考えがあります:変数を非表示にします。

#define READONLY(TYPE, VAR) const TYPE& VAR = this->VAR //C++03
#define READONLY(VARIABLE) const auto& VARIABLE = this->VARIABLE //C++11

class myClass {
    int x;  // This should be prevented to being changed most of the time
    int y;  // Regular variable
    myClass() :x(1), y(2) {}
    void foo1 () {// This can change x
        x++; 
        y++;
    } 
    void foo2 () {// This shouldn't be able to change x
        READONLY(x); //in this function, x is read-only
        x++; //error: increment of read-only variable 'x'
        y++;
    } 
};

変数のロックをバイパスする方法 ( などthis->x) はまだありますが、そのような状況では何もできません。

于 2012-12-13T19:31:17.623 に答える
1

xのメンバーprivatesubClass作成foo1し、 のフレンド機能を作成しsubClassます。このような:

class myClass {
    int y;  // Regular variable
    myClass() : x (1) {}
    void foo1 () {x.x++; y++;} // This can change x
    void foo2 () {x.x--; y--;} // This shouldn't be able to change x
                            // I want it to throw a compile error
    class subClass {
      friend void myClass::foo1() ; // This must come after the declaration of foo1
      int x ; // private
    public:
      subClass (int x) : x (x) { }
      int read_x() const { return x ; }
      } x ;
};

これにより、必要な場所でコンパイラ エラーがスローされます。

于 2012-12-13T19:56:55.360 に答える
1

まあ、それがあなたの努力に値するかどうかはわかりませんが、とにかく、これがクイズまたは sth の場合に備えて、プライベート継承とフレンドを組み合わせてみてください。

class MyClassX {
protected:
  MyClassX() : x(1) {}
  int x;
public:
  int getX() const { return x; } // read only access
};
class MyClassY {
protected:
  MyClassY() : y(0) {}
  int y;
  friend class MyClass;
public:
  int getY() const { return y; }
};
class MyClassXY : private MyClassX, private MyClassY {
public:
    void foo1 () {x++; y++}      // this can change x or y
};
MyClass : public MyClassXY {
public:
    void foo2 () const { y--; }  // this can't change x but can change y
};
于 2012-12-13T19:15:17.480 に答える
1
class myClass {
    int x;
    mutable int y;
public:
    myclass() : x(1) {}
    void foo1 () {x++; y++}      // this can change x or y
    void foo2 () const { y--; }  // this can't change x by can change y
};

メンバー関数constをこのようにマークすると、そのメンバーでオブジェクトのメンバーを変更するようなことはできません (そのメンバーが実際にはオブジェクトのメンバーではないmutable場合を除きます)。staticstatic

これは、そのような変更を行おうとする関数の呼び出しを単に防止するものではないことに注意してください。むしろ、マークされconstているがオブジェクトの状態を変更しようとする関数はまったくコンパイルされません。

ただし、これが本当に最高のデザインであるとはまったく確信していないことを付け加えておきます。むしろ逆に、あなたの要件のように聞こえ、x十分yに複雑であるため、適切な制約を直接強制する個別のクラスとしておそらくより理にかなっているでしょう (たとえば、operator=正しい状況でのみ入力を受け入れるためのオーバーロードを提供することによって)。

言い換えれば、mutable上で示した I've の使用は、(私が思うに) あなたが尋ねた質問に対する最も単純で直接的な答えですが、あなたが本当に質問すべき質問をしていない可能性がかなり高いようです設計を変更することでメリットが得られる可能性が高くなります。残念ながら、より良い設計が何であるかを示唆する「全体像」について十分に語られていません.

于 2012-12-13T19:03:08.637 に答える
0

技術的には、クラスが変数を認識でき、それが定数ではない限り、答えはノーです。変数を変更できます。しかし、ロックしたい変数を別のクラスに分離することで、目的を達成できます。

于 2012-12-13T19:15:42.340 に答える
0

プライベート x 変数を持つクラスを作成します。その中にあなたの方法を書いてください。

このクラスから実際のクラスを派生させます。x ホルダーを実際のクラスのフレンドにします。

X ホルダーは、x ホルダーで CRTP のようなキャスト (ベースへの静的キャスト) を使用して、これを実際のクラスへのポインターに変換します。

x ホルダーから x ゲッターを公開します。

私は気にしませんが、mutable と const を悪用するよりはましです。

于 2012-12-13T19:16:19.340 に答える
0

あなたがやろうとしていることを行うことはできません... 私が間違っている場合は誰かが私を訂正してください。

于 2012-12-13T18:56:25.077 に答える