5

プロパティのようなオブジェクトの実装について何度も議論されてきたことは知っていますが、私が必要としているのは、提案されているさまざまなソリューションとは少し異なります。

必要なのは、変数と同じセマンティクスを持つオブジェクトですが、その値が変更されたときに、何らかのアクションを実行したいと思います。これは、暗黙のget / setメソッドを持ち、演算子=と暗黙の変換演算子のオーバーロードを実装することを意味します。

私が「プロパティのような」を意味するとき、私は必ずしもセマンティックobject.propertyを意味するのではなく、(のように)暗黙のget/setメソッドを持つ方法にすぎないことに注意してくださいproperty-like-variable = value。その理由は、変数を使用する既存のコードがあり、既存のコードを変更せずに変数値が変更されるたびに何らかのアクションを実行したいためです(変数の宣言のみを変更する必要があります)。

私はこのような最小限のコードでこの結果を得ました:

#include <stdio.h>

class Int
{
    int _value;

public:
    // default constructor
    Int() { printf("Int: initial value undefined\n"); }

    // assignment constructor
    Int(int value) : _value(value) { printf("Int: initial value is %d\n", _value); }

    // property get
    operator const int() const { return _value; }

    // property set
    int operator=(int value)
    { 
        _value = value;
        printf("new value is %d\n", value);
        return value;
    }

    // TODO: overload other operators if needed
};

これは使用例です:

class C
{
    Int _i;

public:
    C() : _i(2) { }

    void foo()
    {
        _i = 3;
        printf("foo(): _i = %d\n", _i);
    }
};

int main()
{
    int i;
    Int I;

    i = 1;
    I = i;
    I = I + 1;

    C c;
    c.foo();
}

今いくつかの質問:

  1. この特定の必要性はすでに議論されていますか?デザインパターンはありますか?
  2. 私はここで何か悪いことをしていますか?(実装と設計の両方の観点から)
  3. これを行うことにはパフォーマンス面でいくつかの欠点がありますか、それともコンパイラーはオーバーヘッドなしでそれを最適化することができますか?
  4. この構成を呼び出すためのより良い方法はありますか?これは厳密には「プロパティ」ではないように思われるためです(これは、クラス内の変数を「ボックス化」することに似ているようです)。
  5. これはテンプレートで一般化できますか?値を取得/設定するときにカスタム処理を実行する必要があるため、簡単な方法はわかりません。
4

2 に答える 2

3

広告の質問2:コードに2つの一般的な問題があります。

  1. 宣言の最初のconst修飾子operator const int()は無意味です(gccはそれについて警告します)

  2. 代入演算子の戻り型は、そうでInt&ないint場合は元のintのセマンティクスとは異なるセマンティクスを持ち、次のc++コードはコンパイルされません。

    Int i;
    (i=2)=3;
    

広告質問3:set / get関数が値を割り当て/返す以外に何もしない場合は、完全に最適化する必要があります。ただし、電話をかけるとprintf()、パフォーマンスの問題が深刻に発生する可能性があります;)。

広告の質問5:テンプレートを使用した一般化は、テンプレートの特殊化を介してさまざまなタイプに合わせてカスタマイズすることを含め、非常に簡単に思えます。

template<typename T> class observe
{
    T _value;

public:
    // default constructor
    observe() { cout << "Int: initial value undefined" << endl; }

    // assignment constructor
    observe(const T& v) : _value(v) { cout << "initial value is " << v << endl; }

    // property get
    operator T() const { return _value; }

    // property set
    observe<T>& operator=(const T& value)
    {
        _value = value;
        cout << "new value is " << _value << endl;
        return *this;
    }
};

// special behavior for the assignment of doubles
template<> observe<double>& observe<double>::operator =(const double& value)
{
    _value = value;
    cout << "new double value is " << _value << endl;
    return *this;
}

observe<double> d;
d = 1.0;
于 2013-03-07T13:49:35.683 に答える
0

プロパティのようにするには、「set」コードを内部に含める必要があると思いますclass C。これはどう:

class C
{
public:
    class i_property_class {

...methods from your current Int class

    } i;

...rest of class C
}

それが機能する場合は、の基本クラスを試してi_property_class拡張し、必要なメソッドを提供し、必要に応じてオーバーライドして(継承には注意が必要ですoperator=個別のプロパティごとにカスタム動作を取得することをお勧めします。

次に、質問5について、この基本クラスをテンプレートにすることも機能するはずです。

于 2013-03-07T13:47:54.257 に答える