C++ 对13参数构造函数的改进

C++ 对13参数构造函数的改进,c++,parameters,constructor,C++,Parameters,Constructor,感谢Microsoft提供Intellisense和Atomineer提供Atomineer UTIL…所有这些参数都是必需的且不可变的 有更好的方法吗 /************************************************************************************************** * <summary>Initializes a new instance of the ADTBattleCharacter cl

感谢Microsoft提供Intellisense和Atomineer提供Atomineer UTIL…所有这些参数都是必需的且不可变的

有更好的方法吗

/**************************************************************************************************
 * <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);
/**************************************************************************************************
*初始化ADTBattleCharacter类的新实例。
*角色的名称。
*最大生命值。
*最大的魔力。
*力量。
*敏捷性。
*攻击力。
*国防力量。
*角色携带的黄金。
*这个角色的经历是值得的。
*角色对停止咒语的抵抗力。
*角色对睡眠的抵抗力。
*角色对伤害的抵抗力。
*可用的法术。
**************************************************************************************************/
ADTBattleCharacter(标准::字符串名称、无符号字符最大值、无符号字符最大值、无符号字符最大值、,
无符号字符强度,无符号字符敏捷性,
无符号字符攻击功率,无符号字符防御功率,
未签名短期黄金,未签名短期经验,
双停双抗,双睡双抗,双伤双抗,
std::位集拼写(U列表);

如果目标只是减少提供给构造函数的参数数量,那么有很多方法可以实现。真正的问题是,正如我在第一篇文章的评论中所理解的那样,是否有更简单的方法来管理参数

使参数更易于管理的一种方法是使用通用数据结构来维护它们。有点像地图

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();
    }

};
属性将从继承自
AttrBase
Attr
模板创建

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) {}
};
模板
结构属性:公共属性库{
typedef无符号字符值\u类型;
枚举{默认值=0};
值\类型值;
Attr(value_type v):value(v){
};
模板
结构属性:公共属性库{
typedef std::字符串值\u类型;
静态标准::字符串默认值;
值\类型值;
Attr(value_type v):value(v){
};
模板
结构属性:公共属性库{
typedef无符号短值_type;
枚举{default_value=1};
值\类型值;
Attr(value_type v):value(v){
};

这允许以增量方式添加新属性,而不会增加构造函数的复杂性。此外,相同的属性集合可以传递给不同的实体,每个实体只能对它们感兴趣的属性做出反应。只需要设置属性的子集。可以测试属性的存在,也可以使用默认值。如果要添加和删除动态属性,可以通过添加一个额外的映射来保存它们,从而扩展容器。更好的方法是使用。或者,更简单地说,您可以向当前构造函数声明一个包含所有参数字段的类。参数类本身可以有一个构造函数(或多个构造函数),将字段初始化为合理的默认值,您可以通过直接访问字段来更改值。然后在parameter类中实现一个函数来构造对象,或者定义一个对象构造函数来获取parameter类的一个实例。

看看您的具体情况,在我看来,您并没有很好地解决问题

从概念上讲,系统中的角色具有:

  • 一个名字
  • 一个属性块,包含他们的基本属性(生命、防御等)
  • 角色的次要属性(经验)
  • 一份清单,其中包括他们当前的法术列表和他们的金币,以及其他可能的物品
这是4个参数,不是13个。当您编写一个函数时,您会发现它需要大量的参数,这些参数中的一些在概念上相互关联的可能性很大。其他函数也可能希望使用这些链接参数

例如,您可能希望显示角色的统计块。这样做的功能真的需要角色吗?不它只需要统计块。所以它应该是一个stat块对象


就像角色的构造函数一样。

你不能将它们全部打包到某个容器对象中并传递给它?将它们放入一个结构中,给出默认值或基于其他值,更改所需的值,然后将结构传递给?@chris,这只会将问题推给结构的构造函数。没有改变任何东西。@Mark:struct为什么需要构造函数?它是一个结构;类型的集合。它不是一个智能物体;这只是一包东西。@NicolBolas,关键是任何适合填充结构的解决方案都适合于首先创建对象。使用结构是一个不必要的中间步骤。请对否决票发表意见,这样我就知道要修改什么了。谢谢-1:这更糟糕。至少对于具有多个参数的构造函数,参数具有合理的名称。用C++的基本类型来分组属性在功能上是没有意义的。如果你要把它们分组,那么就用一些真正有意义的东西来做。这不会降低复杂性,也不会让它变得更加模糊。最好传递一个'config'对象或封装参数的东西。@Nicolas:我理解这个问题,我正在解决参数数量的问题。我的新帖子允许在可查询对象中维护属性。@seand:谢谢您的反馈。我想我的新帖子解决了这个问题。正如Alan J Perlis所说:“如果你有一个包含十个参数的过程,你可能会遗漏一些。”我明白你的观点,但是“用对象替换参数”重构并不能缓解问题,只是将它移到另一个位置
template <AttrTag> struct Attr;

struct AttrBase {
    virtual ~AttrBase () {}
    template <AttrTag TAG> Attr<TAG> * attr_cast () {
        return dynamic_cast<Attr<TAG> *>(this);
    }
};
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) {}
};