11

Intellisense については Microsoft に感謝し、Atomineer Utils については Atomineer に感謝します...これらのパラメーターはすべて必須であり、不変です。

これを行うより良い方法はありますか?

/**************************************************************************************************
 * <summary>Initializes a new instance of the ADTBattleCharacter class.</summary>
 * <param name="name">         The name of the character.</param>
 * <param name="max_HP">       The maximum hit points.</param>
 * <param name="max_MP">       The maximum magic power.</param>
 * <param name="strength">     The strength.</param>
 * <param name="agility">      The agility.</param>
 * <param name="attack_power"> The attack power.</param>
 * <param name="defense_power">The defense power.</param>
 * <param name="gold">         The gold carried by the character.</param>
 * <param name="experience">   The experience the character is worth.</param>
 * <param name="stop_resist">  The character's resistance to stopspell.</param>
 * <param name="sleep_resist"> The character's resistance to sleep.</param>
 * <param name="hurt_resist">  The character's resistance to hurt/hurtmore.</param>
 * <param name="spell_list">   Available spells.</param>
 **************************************************************************************************/
ADTBattleCharacter(std::string name, unsigned char max_HP, unsigned char max_MP,
                   unsigned char strength, unsigned char agility,
                   unsigned char attack_power, unsigned char defense_power,
                   unsigned short gold, unsigned short experience,
                   double stop_resist, double sleep_resist, double hurt_resist,
                   std::bitset<SPELL_MAX> spell_list);
4

3 に答える 3

33

あなたの特定のケースを見ると、あなたは物事をうまく解決していないように私には思えます。

概念的には、システム内のキャラクターには次のものがあります。

  • 名前。
  • 基本的な統計(HP、防御など)を含む統計ブロック。
  • キャラクターの二次属性(経験)。
  • インベントリ。これには、現在の呪文のリストとゴールドなどが含まれる可能性があります。

これは13ではなく4つのパラメーターです。関数を作成していて、多数のパラメーターを使用していることがわかる場合、それらのパラメーターの一部が概念的に相互にリンクされている可能性があります。また、他の関数がこれらのリンクされたパラメーターを使用する可能性もあります。

たとえば、キャラクターの統計ブロックを表示したい場合があります。これを行う関数には本当に文字が必要ですか?いいえ; statブロックが必要です。したがって、統計ブロックオブジェクトを取得する必要があります。

キャラクターのコンストラクターと同じように。

于 2012-06-17T02:53:46.867 に答える
1

より良い方法は、Builder デザイン パターンを使用することです。または、より簡単に言えば、すべてのパラメーターのフィールドを含むクラスを現在のコンストラクターに宣言できます。パラメーター クラス自体は、フィールドを適切な既定値に初期化するコンストラクター (またはコンストラクター) を持つことができ、フィールドに直接アクセスして値を変更します。次に、パラメーター クラスに関数を実装してオブジェクトを構築するか、パラメーター クラスのインスタンスを受け取るオブジェクト コンストラクターを定義します。

于 2012-06-17T02:46:40.230 に答える
0

コンストラクターに提供される引数の数を減らすことが目的である場合、それを達成する方法はたくさんあります。本当の問題は、コメントから私の最初の投稿まで理解しているように、パラメーターを管理するより簡単な方法があるかどうかです。

パラメータの管理を容易にする 1 つの方法は、一般的なデータ構造を使用してパラメータを維持することです。地図のようなもの。

enum AttrTag { AT_Name, AT_Max_HP, AT_Max_MP, //...
               AT_Spells };

struct Attributes {
    typedef std::unique_ptr<AttrBase> AttrPtr;
    typedef std::map<AttrTag, AttrPtr> AttrMap;
    AttrMap attributes;

    template <AttrTag TAG>
    typename Attr<TAG>::value_type get_attr () const {
        AttrMap::const_iterator i = attributes.find(TAG);
        if (i != attributes.end()) return i->second->attr_cast<TAG>()->value;
        return Attr<TAG>::default_value;
    }

    template <AttrTag TAG>
    void set_attr (typename Attr<TAG>::value_type value) {
        attributes[TAG] = AttrPtr(new Attr<TAG>(value));
    }

    bool has_attr (AttrTag t) const {
        return attributes.find(t) != attributes.end();
    }

};

そして、それは次のように使用されます:

Attributes attrs;
attrs->set_attr<AT_Gold>(100);
//...
ADTBattleCharacter(attrs);
//...
unsigned short g = attrs->get_attr<AT_Gold>();

AttrBase属性は、実際の属性に委任する方法を知っているクラスから外れます。

template <AttrTag> struct Attr;

struct AttrBase {
    virtual ~AttrBase () {}
    template <AttrTag TAG> Attr<TAG> * attr_cast () {
        return dynamic_cast<Attr<TAG> *>(this);
    }
};

Attrまた、属性は、から継承するテンプレートを特殊化して作成されAttrBaseます。

template <AttrTag TAG>
struct Attr : public AttrBase {
    typedef unsigned char value_type;
    enum { default_value = 0 };
    value_type value;
    Attr (value_type v) : value(v) {}
};

template <>
struct Attr<AT_Name> : public AttrBase {
    typedef std::string value_type;
    static std::string default_value;
    value_type value;
    Attr (value_type v) : value(v) {}
};

template <>
struct Attr<AT_Gold> : public AttrBase {
    typedef unsigned short value_type;
    enum { default_value = 1 };
    value_type value;
    Attr (value_type v) : value(v) {}
};

これにより、コンストラクターの複雑さを増すことなく、新しい属性を段階的に追加できます。さらに、属性の同じコレクションを異なるエンティティに渡すことができ、それぞれが関心のある属性のみに反応することができます。属性のサブセットのみを設定する必要があります。属性の存在をテストしたり、デフォルト値を使用したりできます。動的属性を追加および削除する場合は、それらを保持するための追加のマップを追加することで、コンテナーを拡張してそのようにすることができます。

于 2012-06-17T02:41:35.037 に答える