我有以下类的层次结构:
class Human {
void foo()=0; //abstract
int age;
bool sex;
double size;
Human(int pAge,bool pSex,double pSize) : age(pAge), sex(pSex), size(pSize)
}
class MetaHuman : Human { //abstract
double power;
bool fly;
bool heal;
MetaHuman(int pAge,bool pSex,double pSize,double pPower,bool pFly,bool pHeal) : Human(...), power(pPower),fly(pFly),heal(pHeal) }
class SuperHuman : MetaHuman {
void foo() const {}; //non abstract
bool xray;
bool inspace;
double teleportation;
SuperHuman(int pAge,bool pSex,double pSize,double pPower,bool pFly,bool pHeal,bool pXray,bool pInspace,double pTeleportation) :
MetaHuman(...),xray(pXray),inspace(pInspace),teleportation(pTeleportation)
}
正如您所看到的,我只是在每个派生类中重复基类构造函数的所有参数,并相对于派生类添加几个参数。
有没有任何方式/模式/设计可以避免重写这样的一切?
答案 0 :(得分:3)
当涉及到严格的OOP时,通常通过将参数封装在结构体中来处理这些问题:
struct HumanData {
int pAge,
bool pSex,
double pSize,
double pPower,
bool pFly,
bool pHeal
}
或者,您可以创建一个构造以在MetaHuman基础上创建SuperHuman。
只是一个提示,因为我看到你正在尝试一些游戏开发。 通常在结构中包装属性,“付出很多”。 所以让你的SEX成为一个基于bool的枚举(我知道,有点矫枉过正:))。您可以在此处阅读C ++ 0x中基于类的枚举:http://blog.smartbear.com/c-plus-plus/closer-to-perfection-get-to-know-c11-scoped-and-based-enum-types/
您将获得额外的强类型类数据,几乎不会影响性能。
作为旁注:您是否确定需要使您的班级层次结构如此陡峭?正如Stroustrup所说:“不要立即为你的所有课程创造一个独特的基础。通常情况下,如果没有它可以为很多/大多数课程做得更好。” - 这是非常准确的。
C ++不是C#/ Java - 强迫它如此,只会让它反叛。
答案 1 :(得分:1)
如果您的问题是参数的绝对数量,您可以使用结构减少。 创建一个名为 humanData 的结构体,其中包含年龄,性别等字段,并询问其余部分。然后派生的构造函数将如下所示:
MetaHuman(humanData, metaHumanData)
如果你喜欢这个并希望更进一步,你甚至可以让humanData成为metaHumanData中的一个成员。
答案 2 :(得分:0)
SuperHuman(specific parameters) : MetaHuman(normalHuman), xray(...), etc
或
SuperHuman(MetaHuman normalHumanBeforeMutation, <specific params>): MetaHuman(normalHumanBeforeMutation), ...
答案 3 :(得分:0)
简单的答案是否定的。
如果您希望能够使用SuperHuman
和xray
创建sex
,那么您必须能够将这两者都传递到构造函数中。
如果限制构造函数参数非常重要,有两种选择:
SuperHuman(int pAge = 0, bool pSex = false, double pSize = 0.0, double pPower = 0.0, bool pFly = false, bool pHeal = false, bool pXray = false, bool pInspace = false, double pTeleportation = 0.0)
默认你的构造函数意味着你只需要将参数传递给你想发送的最后一个非默认参数:
SuperHuman SuperMan(29, true, 225, numeric_limits<double>::infinity(), true, true, true); //pInspace = false and pTeleportation = 0.0
您还可以创建一个构造函数,该构造函数接受父对象并默认所有其他值以供以后初始化:
SuperHuman(const MetaHuman& pMetaHuman) : MetaHuman(pMetaHuman), xray(false), inspace(false), teleportation(0.0){}
请注意,第二种方法意味着您可能无法使用该构造函数const SuperHuman
。