1

Let's say I have a Human class:

class Human {
public:
    bool isFemale;
    double height;
    Human(bool isFemale, double height) {
        this->isFemale = isFemale;
        this->height = height;
    }
};

and derived classes, such as Female and Male, which implement their own methods. Do I have a way, in C++11, to determine at runtime, depending on the inputs into the Human constructor, which "sub-type" (Male or Female) Human should be? I am putting different behaviour for Male and Female in their respective classes. What I am trying to do is determine at runtime whether Human is of type Female or of type Male, depending on constructor input, so I can (afterwards) apply appropriate behaviour based on its type. The ideal would be to always call the Human constructor, and the appropriate sub-type to be chosen at runtime, depending on the parameters one enters in the constructor. If that is possible, I guess one should twist the "Human" constructor, but I'm unsure how...

JFMR
  • 23,265
  • 4
  • 52
  • 76
GabCaz
  • 99
  • 1
  • 11
  • You are already assigning `isFemale` at run time. – JFMR Feb 03 '20 at 10:19
  • I am assigning this property to Human; now I am wondering whether the object type could be "Female" based on this property (ie dispatch object type depending on based constructor parameter). The objective afterwards is to call all appropriate methods on Human, depending on the appropriate sub-type, without necessarily using (if (isFemale...)... if(!isFemale...)). (added to post) – GabCaz Feb 03 '20 at 10:23
  • 1
    are you looking for a factory design pattern? – mfnx Feb 03 '20 at 10:25
  • 2
    Why are you trying to do this? If you want different behaviour for Male and Female, you should put that in their respective classes. – Indiana Kernick Feb 03 '20 at 10:27
  • @Kerndog73, indeed, I am putting different behavior for Male and Female in their respective classes. What I am trying to do is determine at runtime whether Human is of type Female or of type Male, depending on constructor input, so I can (afterwards) apply appropriate behavior based on its type. Sorry for the confusion... – GabCaz Feb 03 '20 at 10:30
  • 1
    `Human`'s constructor can only create a `Human` (even if it is the `Human` sub-object of some derived class). What you are looking for might be a factory function. – Mat Feb 03 '20 at 10:32
  • If you want to construct a female, invoke the `Female` constructor. Why do you want to create a `Human` but then turn it into a `Female` or a `Male`? – Indiana Kernick Feb 03 '20 at 10:32
  • Thats not the task of the human class. You should write a separate function that decides whether the Male of Female C-str should be called. – HWilmer Feb 03 '20 at 10:32
  • @mfnx I did not know the expression "factory design pattern"; looking on the Wikipedia page indeed it seems appropriate to my situation! – GabCaz Feb 03 '20 at 10:33

2 Answers2

7

By calling Human's constructor, you can only create a Human object.

As far as I understand you want to create either a Male or Female object depending on the gender input that you obtain at run time. Then, you should probably consider a factory function for achieving this.

For example, if you define Male and Female as:

struct Male: public Human {
   Male(double height): Human(false, height) {}
   // ...
};

struct Female: public Human {
   Female(double height): Human(true, height) {}
   // ...
};

Then, you can use the following factory function, make_human():

std::unique_ptr<Human> make_human(bool isFemale, double height) { 
   if (isFemale)
      return std::make_unique<Female>(height);
   return std::make_unique<Male>(height);
}

It decides at run time whether to create a Female or a Male object based on the argument passed to the isFemale parameter.

Just remember to make Human's destructor virtual because both Male and Female classes publicly inherit from Human.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
JFMR
  • 23,265
  • 4
  • 52
  • 76
3

Notice that your design allows for Male with isFemale = "true", you can delegate this action internally avoiding erroneous flags, for sample purposes you can do something like this: Live Sample

#include <iostream>

class Human {
private:
    int height;

protected:
    bool isFemale;

public:
    Human(){};
    Human(int height, bool isFemale = false) : height(height) {}
    virtual ~Human(){}
};

class Female : public Human {
public:
    Female(int height) : Human(height, true) {
        std::cout << "I'm a new Female, my height is " << height << std::endl;
    }
};

class Male : public Human {
public:
    Male(int height) : Human(height, false) {
        std::cout << "I'm a new Male, my height is " << height << std::endl;
    }
};

You can than call the appropriate constructor, for instance:

int main() {

    char gender;
    Human h;

    std::cout << " enter m/f: ";
    std::cin >> gender;

    switch(gender){
        case 'm':
        case 'M':
          h = Male(186);
            break;
        case 'f':
        case 'F':  
          h = Female(175);
          break;
    }
}

If you want to take advantage of polymorphism, take a look at this thread.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • @idclev463035818 it's what the OP wants. for me I would just define it internally. – anastaciu Feb 03 '20 at 11:12
  • Yes, that's not a very good design, but if you notice, in the accepted answer he is confortable with that, I will change my answer to provide an alternative. – anastaciu Feb 03 '20 at 11:18