1

継承階層があり、この階層の各クラスに、そのクラスに固有で、プログラムの実行中に変更されない一連の属性を持たせたいと考えています。例えば:

class Base
{
public:
    const std::string getName() const;
    bool getAttribute1() const;
    int getAttribute2() const;
};

今、これらの関数が常に同じ結果を返すようにしたいと考えています。さらに、別のクラスが継承する場合、Baseこのクラスは独自の属性セットを持つ必要があり、この派生クラスのインスタンスは同じ属性を持つ必要があります。また、名前はクラスごとに一意にする必要があります。

これをできるだけ透明でエレガントにする方法を知りたいです。私が使用できる2つのアイデアを検討しました:

  1. いくつかのロック システムを作成します。

つまり、これらの属性のセッターを提供しますが、それらが複数回呼び出されたときに実行時例外をスローするようにします。

  1. ゲッターを純粋仮想にします。

この場合、関数の結果はオブジェクト自体の内部には格納されません。これにより、結果が動的タイプに依存することが漠然と明確になります。

どちらのアイデアも信じられないほどお粗末に聞こえるので、あなたの助けが必要です.

私は C++ は初めてですが、このような一般的な問題を解決するためのイディオムやパターンがたくさんあることは知っています。何でも知ってますか?

4

2 に答える 2

4

継承階層があり、この階層の各クラスに、そのクラスに固有で、プログラムの実行中に変更されない一連の属性を持たせたい

では、対応する値を引数としてクラス コンストラクターに提供するだけで、パブリック インターフェイスでセッター メソッドを公開しないでください。これにより、オブジェクトの存続期間中、値が一定に保たれます。

これらのデータ メンバーの値をクラスのメンバー関数 (もちろんプライベート データにアクセスできます) から変更する可能性のあるエラーから保護するには、それらのデータ メンバーを作成しますconst。これにより、コンストラクターの初期化子リストでこれらのメンバーを初期化する必要があることに注意してください。

class Base
{
public:
    // Forwarding constructor (requires C++11)
    Base() : Base("base", true, 42) { }
    const std::string getName() const { return _s; }
    bool getAttribute1() const { return _a1; }
    int getAttribute2() const { return _a2; }

protected:
    // Constructor that can be called by derived classes
    Base(std::string s, bool a1, int a2)
    : _s(s), _a1(a1), _a2(a2) { }

private:
    const std::string _s;
    const bool _a1;
    const bool _a2;
};

派生クラスは、適切な引数を使用してベース サブオブジェクトを構築するだけです。

class Derived : public Base
{
public:
    // Provide the values for the constant data members to the base constructor
    Derived() : Base("derived", false, 1729) { }
};

この方法では、仮想関数呼び出しのオーバーヘッドが発生せず、派生クラスのこれらのメンバーごとに同様の仮想関数を書き直す必要がありません。

于 2013-03-29T09:55:09.707 に答える
2

それらを仮想化し、関数が返す結果をハードコーディングします。

class Base
{
public:
    virtual const std::string getName() const { return "BaseName"; }
    virtual bool getAttribute1() const { return whatEverAttributeValueYouWant; }
    virtual int getAttribute2() const { return attributeValueHere; }
};

class Derived : public Base {
public:
    virtual const std::string getName() const { return "DerivedName"; }
    virtual bool getAttribute1() const { return whatEverOtherAttributeValueYouWant; }
    virtual int getAttribute2() const { return otherAttributeValueHere; }
};

オブジェクトではなくクラスを記述したい場合は、(一種の) 特性を使用します。

template<class T> struct AttributeValues;

template<> struct AttributeValues<Base> {
    static const std::string name () { return "BaseName"; }
};

template<> struct AttributeValues<Derived> {
    static const std::string name () { return "DerivedName"; }
};

//...

auto nameBase = AttributeValues<Base>::name ();
auto nameDerived = AttributeValues<Derived>::name ();
于 2013-03-29T09:49:37.487 に答える