如何避免在 C++ 中的派生 class 中重复基本 class 构造函数参数?
How to avoid repeating base class constructor parameters in derived class in C++?
我有以下 class 的层次结构:
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)
}
如您所见,我只是在每个派生 class 中重复基本 class 构造函数的所有参数,并添加一些与派生 class 相关的参数。
是否有任何 way/pattern/design 可以避免像这样重写所有内容?
事实上,您需要这些价值观才能完全定义超人。如果你想创建更多基于同一个超人的超人,你可以创建一个默认的超人,在超人中实现复制构造函数(无论如何你都应该这样做),然后做一些像
SuperHuman(specific parameters) : MetaHuman(normalHuman), xray(...), etc
或
SuperHuman(MetaHuman normalHumanBeforeMutation, <specific params>): MetaHuman(normalHumanBeforeMutation), ...
如果你的问题是参数的数量太多,你可以用结构来减少。
创建一个名为 humanData 的结构,其中包含年龄、性别等字段,然后询问其余部分。然后派生的构造函数将如下所示:
MetaHuman(humanData, metaHumanData)
如果您喜欢它并想更进一步,您甚至可以将 humanData 设为 metaHumanData 的成员。
对于严格的OOP,此类问题通常通过将参数封装在结构中来处理:
struct HumanData {
int pAge,
bool pSex,
double pSize,
double pPower,
bool pFly,
bool pHeal
}
或者,您可以构造一个在超人基础上创建超人的结构。
只是一个提示,因为我看到你正在尝试一些游戏开发。
通常在结构中包装属性,'pays off a lot'。
所以让你的 SEX 成为一个基于布尔的枚举(我知道,有点矫枉过正 :))。您可以在此处阅读 C++0x 中基于 class 的枚举:http://blog.smartbear.com/c-plus-plus/closer-to-perfection-get-to-know-c11-scoped-and-based-enum-types/
您将获得超强类型的 class 数据,几乎不会影响性能。
附带说明:您绝对确定需要将 class 层次结构设置得如此陡峭吗?正如 Stroustrup 所说 "Don’t immediately invent a unique base for all of your classes. Typically, you can do better without it for many/most classes." - 这非常准确。
C++ 不是 C#/Java - 强迫它如此,只会让它叛逆。
简单的答案是否定的。
如果您希望能够使用 xray
和 sex
创建一个 SuperHuman
,那么您必须能够将它们都传递给构造函数。
如果限制构造函数参数非常重要,则有两个选项可供您选择:
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
。
我有以下 class 的层次结构:
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)
}
如您所见,我只是在每个派生 class 中重复基本 class 构造函数的所有参数,并添加一些与派生 class 相关的参数。
是否有任何 way/pattern/design 可以避免像这样重写所有内容?
事实上,您需要这些价值观才能完全定义超人。如果你想创建更多基于同一个超人的超人,你可以创建一个默认的超人,在超人中实现复制构造函数(无论如何你都应该这样做),然后做一些像
SuperHuman(specific parameters) : MetaHuman(normalHuman), xray(...), etc
或
SuperHuman(MetaHuman normalHumanBeforeMutation, <specific params>): MetaHuman(normalHumanBeforeMutation), ...
如果你的问题是参数的数量太多,你可以用结构来减少。 创建一个名为 humanData 的结构,其中包含年龄、性别等字段,然后询问其余部分。然后派生的构造函数将如下所示:
MetaHuman(humanData, metaHumanData)
如果您喜欢它并想更进一步,您甚至可以将 humanData 设为 metaHumanData 的成员。
对于严格的OOP,此类问题通常通过将参数封装在结构中来处理:
struct HumanData {
int pAge,
bool pSex,
double pSize,
double pPower,
bool pFly,
bool pHeal
}
或者,您可以构造一个在超人基础上创建超人的结构。
只是一个提示,因为我看到你正在尝试一些游戏开发。 通常在结构中包装属性,'pays off a lot'。 所以让你的 SEX 成为一个基于布尔的枚举(我知道,有点矫枉过正 :))。您可以在此处阅读 C++0x 中基于 class 的枚举:http://blog.smartbear.com/c-plus-plus/closer-to-perfection-get-to-know-c11-scoped-and-based-enum-types/
您将获得超强类型的 class 数据,几乎不会影响性能。
附带说明:您绝对确定需要将 class 层次结构设置得如此陡峭吗?正如 Stroustrup 所说 "Don’t immediately invent a unique base for all of your classes. Typically, you can do better without it for many/most classes." - 这非常准确。
C++ 不是 C#/Java - 强迫它如此,只会让它叛逆。
简单的答案是否定的。
如果您希望能够使用 xray
和 sex
创建一个 SuperHuman
,那么您必须能够将它们都传递给构造函数。
如果限制构造函数参数非常重要,则有两个选项可供您选择:
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
。