6

次のクラスについて考えてみます。

class MyClass1
{
    public:
        double x() const {return _x;} // getter
        double y() const {return _y;} // getter
        double z() const {return _x*_y;} // getter
        void x(const double var) {_x = var;} // setter
        void y(const double var) {_y = var;} // setter
        void z(const double var) {_x = var; _y = 1;} // setter
    protected:
        double _x;
        double _y;
};

の実際のコンテンツMyClass1は実装の詳細であるため、ゲッターとセッターは、相互依存している場合でも、クラスのコンテンツを取得および設定するための統一された方法を提供します(ここで_zは内部には存在しませんが、ユーザーにとっては、およびzのような変数です)。xy

ここで、とのゲッター/セッターを作成する必要をなくすためにxy次のようなラッパーを使用できます。

template <typename Type>
class Wrapper
{
    public:
        constexpr Wrapper(const Type& value) {_value = value;}
        constexpr Type& operator()() {return _value;}
        constexpr const Type& operator()() const {return _value;}
        constexpr void operator()(const Type& value) {_value = value;}
    protected:
        _value;
};

そして今、元のクラスは次のようになります。

class MyClass2
{
    public:
        Wrapper<double> x;
        Wrapper<double> y;
        double z() const {return x*y;} // getter
        void z(const double var) {x = var; y = 1;} // setter
};

ゲッター/セッターを書かなければならないのを避けるのは危険な習慣ですか、それとも良い解決策ですか?

注:ここMyClass1MyClass2は単なる例です。私の質問は非常に「一般的」です。ゲッターWrapper/セッターが内部値を返す/設定するだけの場合、クラスのゲッター/セッターを提案されたものに置き換えるのは危険ですか。

4

3 に答える 3

1

前述のように、ゲッターとセッターの主な目的は、プライベートインスタンス変数にアクセスして設定するための統一された方法を提供することです。

ラッパーソリューションから、プログラムライフサイクルの途中でセッターを変更することにした場合は、ラッパーを破棄して、MyClass1のように元のゲッター/セッターに置き換えることができます-他のすべてのコンポーネントを変更する必要はありませんそれを呼び出すコード。

したがって、その時点から、あなたのソリューションは、余分な数行のコードを入力する手間を省くための有効な方法だと思います。

于 2013-01-25T05:22:09.380 に答える
1

そこには特に危険なものは見当たりませんが、何も得られていないようです。C ++は、setter関数と互換性のない、あらゆる種類のオブジェクトの参照セマンティクスを提供します。実際の内容が単なる詳細ではない場合もあります。

逆の方法も使用できます(実際、これは、この質問をクリックしたときに表示されると予想されていたものです)。

struct virt_z {
    double x;
    double y;
    struct z_wrap {
        virt_z &parent;

        operator double() { return parent.x * parent.y; }
        z_wrap &operator=( double in ) {
            parent.x = in;
            parent.y = 1;
            return *this;
        }
        z_wrap( virt_z &in ) : parent( in ) {}
    } z;

    virt_z() : z( *this ) {}
    virt_z( virt_z const &o ) : x( o.x ), y( o.y ), z( *this ) {}
};

https://ideone.com/qqgj3D

于 2013-01-25T05:24:35.123 に答える
1

それ自体は危険ではなく、(クラスのユーザーにとって)使用するのがより難しいだけです。MyClass2は、インターフェイスをわかりにくくし、乱雑にします。

コードを書くのは面倒ではないかもしれませんが、コードを書く必要があるのは1回だけです。インターフェースは何度も再利用されます。したがって、コードリーダーを優先する必要があります。

このため、MyClass1はMyClass2とPotatoswatterの両方のソリューションよりも優れています。

(これを行う方法がC ++にあったとしても:

class MyClass3
{
    double x, y, z;
}

MyClass3::z::operator=(double) { ... } // property set
double MyClass3::z::operator() { ... } // property get

C#のように、この種の「隠された」コードはデバッグを遅くする可能性のある悪い仮定につながるため、それでも悪い考えだと思います。関数スタイルでは、少なくとも、プリミティブコピーよりも複雑なことが起こっている可能性があると考えることができます。)

于 2013-01-25T07:19:23.060 に答える