感谢Microsoft for Intellisense和Atomineer for Atomineer Utils ...所有这些参数都是必需且不可变的。
有更好的方法吗?
/**************************************************************************************************
* <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);
答案 0 :(得分:33)
看看你的具体案例,在我看来你没有把事情搞得很好。
从概念上讲,系统中的角色有:
这是4个参数,而不是13.当你编写一个函数,并且你发现它正在采用大量参数时,其中一些参数在概念上相互关联的可能性很大。 其他函数想要使用这些链接参数的几率也很高。
例如,您可能想要显示角色的统计数据块。执行此操作的功能是否真的需要字符?没有;它只需要stat块。所以它应该采用stat块对象。
就像角色的构造函数一样。
答案 1 :(得分:1)
更好的方法是使用Builder design pattern。或者,更简单地说,您可以声明一个包含当前构造函数的所有参数的字段的类。参数类本身可以有一个构造函数(或构造函数),用于将字段初始化为合理的默认值,并通过直接访问字段来更改值。然后在参数类中实现一个函数来构造你的对象,或者定义一个接受参数类实例的对象构造函数。
答案 2 :(得分:0)
如果目标只是减少提供给构造函数的参数数量,那么有很多方法可以实现。真正的问题是,正如我从第一篇文章的评论中所理解的那样,是否有更简单的方法来管理参数。
使参数更易于管理的一种方法是使用通用数据结构来维护它们。像地图一样。
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
的{{1}}模板来创建。
AttrBase
这允许以增量方式添加新属性,而不会增加构造函数的复杂性。此外,可以将相同的属性集合传递给不同的实体,并且每个属性只能对它们感兴趣的那些属性作出反应。只需要设置一部分属性。可以测试属性的存在,或者可以使用默认值。如果要添加和删除动态属性,可以通过添加其他地图来扩展容器,以便保存它们。