如何避免在C++中的派生类中重复基类构造函数参数

How to avoid repeating base class constructor parameters in derived class in C++?

本文关键字:基类 参数 构造函数 派生 何避免 C++      更新时间:2023-10-16

我有以下类的层次结构:

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

正如你所看到的,我只是在每个派生类中重复基类构造函数的所有参数,并添加相对于派生类的几个参数。

有什么方法/模式/设计可以避免像这样重写所有内容吗?

当涉及到严格的OOP时,这些问题通常通过将参数封装在structs:中来处理

struct HumanData {
    int pAge, 
    bool pSex,
    double pSize,
    double pPower,
    bool pFly,
    bool pHeal
}

或者,你可以制作一个结构,在MetaHuman的基础上创建一个超人。

只是一个提示,因为我看到你正在尝试一些游戏开发。通常将属性包装在结构中,"会得到很多回报"。所以,让你的SEX成为一个基于布尔的枚举(我知道,有点过头了:)。您可以在此处阅读C++0x中基于类的枚举:https://smartbear.com/blog/closer-to-perfection-get-to-know-c11-scoped-and-ba/?feed=develop

您将获得额外的强类型类数据,几乎不会对性能产生影响。

顺便说一句:你绝对确定你需要让你的阶级等级制度如此陡峭吗?正如斯特劳斯特鲁普所说的";不要立即为你的所有类创建一个独特的基础。通常,对于许多/大多数类来说,没有它可以做得更好"-这是非常准确的。

C++不是C#/Java——强迫它这样做只会让它反叛。

如果你的问题是参数的数量太多,你可以用structs来减少。创建一个名为humanData的结构,该结构包含年龄、性别等字段,并询问其余字段。然后派生的构造函数将如下所示:

MetaHuman(humanData, metaHumanData) 

如果你喜欢这个并想更进一步,你甚至可以让humanData成为metaHumanData的成员。

实际上,您需要这些值来完全定义SuperHuman。如果你想在同一个MetaHuman上创建更多的超人,你可以创建一个默认的MetaHuman,在MetaHuman中实现复制构造函数(无论如何你都应该这样做),然后做一些类似的事情

SuperHuman(specific parameters) : MetaHuman(normalHuman), xray(...), etc

SuperHuman(MetaHuman normalHumanBeforeMutation, <specific params>): MetaHuman(normalHumanBeforeMutation), ...

简单的答案是否定的。

如果您希望能够使用xraysex创建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

相关文章: