Reputation: 209
I have the following hierarchy of 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)
}
As you can see i just repeat all parameters of the base class constructor down in each derived class and add couple parameters relative to the derived class.
Is there any way/pattern/design to avoid having to rewrite everything like this ?
Upvotes: 3
Views: 1877
Reputation: 769
When it comes to strict OOP, such issues are usually handled by encapsulating the parameters in structs:
struct HumanData {
int pAge,
bool pSex,
double pSize,
double pPower,
bool pFly,
bool pHeal
}
Alternatively, you could make a construct to create a SuperHuman on a MetaHuman base.
Just a hint, as I see you're trying some game dev. Usually wrapping attributes in structures, 'pays off a lot'. So make your SEX a bool based enum (i know, a little bit overkill :)). You can read about based class enums in C++0x here: https://smartbear.com/blog/closer-to-perfection-get-to-know-c11-scoped-and-ba/?feed=develop
You will get extra strongly typed class data, with almost no performance impact.
As a side note: Are you absolutely sure you need to make your class hierarchy so steep? As Stroustrup said "Don’t immediately invent a unique base for all of your classes. Typically, you can do better without it for many/most classes." - which is quite accurate.
C++ is not C#/Java - forcing it to be so, will only make it rebel.
Upvotes: 5
Reputation: 38919
The simple answer is no.
If you want to be able to create a SuperHuman
with xray
and sex
then you must be able to pass both of those into the constructor.
There are two options available to you though if limiting your constructor arguments is very important:
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)
Defaulting your constructor will mean you only need to pass in the arguments up to the last non-default argument you want to send so:
SuperHuman SuperMan(29, true, 225, numeric_limits<double>::infinity(), true, true, true); //pInspace = false and pTeleportation = 0.0
You can also create a constructor that takes the parent object and default all the other values for later initialization:
SuperHuman(const MetaHuman& pMetaHuman) : MetaHuman(pMetaHuman), xray(false), inspace(false), teleportation(0.0){}
Be aware that this second method means that you probably couldn't have const SuperHuman
s with that constructor.
Upvotes: 0
Reputation: 1161
If your problem is the sheer number of parameters, you can reduce then with structs. Create a struct called humanData which has fields like age, sex, and ask the rest. Then the constructor of the derived will look like so :
MetaHuman(humanData, metaHumanData)
If you like this and want to take it one step further, you might even make humanData a member in metaHumanData.
Upvotes: 1
Reputation: 769
You, in fact, need those values to completely define a SuperHuman. If you want to create more Superhumans based on same MetaHuman, you could create a default MetaHuman, implement copy constructor in MetaHuman (thing that you should to anyway), and then do something like
SuperHuman(specific parameters) : MetaHuman(normalHuman), xray(...), etc
or
SuperHuman(MetaHuman normalHumanBeforeMutation, <specific params>): MetaHuman(normalHumanBeforeMutation), ...
Upvotes: 0