문제

I have written a pretty small program where you type in whether you are a boy or a girl and it prints out a statement. My main question is that from my code is there any easier way of writing for the women beside copying and pasting from the base class. Here is my code

#include <iostream>
#include <string>


class Man{
protected:
    std::string name;
public:
    void getInfo(std::string hName){
        name = hName;
    }
    void showInfo(){
        std::cout << "Your name is: " << name << std::endl;
        std::cout << "And you are a MAN" << std::endl;
    }
};

class Women{ //is there an easier way to write this         
protected:
    std::string fem_name;
public:
    void getfemInfo(std::string fhName){
        fem_name = fhName;
    }
    void showfemaleInfo(){
        std::cout << "Your name is: " << fem_name << std::endl;
        std::cout << "And you are a Women" << std::endl;    
    }
};

class Human:public Man, public Women{
public:
    Human(){}
};

int main(){
    //local variables
    std::string choice;
    std::string tName;
    //declaring objects 
    Human person;
    //user interface
    std::cout << "Please enter you name: ";
    std::cin >> tName;
    std::cout << "Are you a [boy/girl]: ";
    std::cin >> choice;
    //if handler
    if (choice == "boy"){
        person.getInfo(tName);
        person.showInfo();
    }else if(choice == "girl"){
        person.getfemInfo(tName);
        person.showfemaleInfo();
    }
    system("pause");
    return 0;
}

When I try to derive class Woman from class Man, it makes person.getInfo(tName) and person.showInfo() ambiguous. Why is that? And how can I make this code smaller (for the women).

도움이 되었습니까?

해결책

You've got it backwards - public inheritance represents IS-A relationship. So your usage is saying that "every human is a man, and every human is a woman." That doesn't really work. Public inheritance should never be used as just a convenience for "getting all the functionality in one spot." That's what composition (or at worst, non-public inheritance) is for.

Your situation is a great example for employing inheritance, though. It just has to follow its natural definition (every man is a human; every woman is a human). That is, make Human the base class and implement all shared functionality there. Something like this:

class Human
{
protected:
  std::string name;

  virtual std::string getGenderString() const = 0;

public:
  virtual ~Human() {}  //dtor must be virtual to be usable as a polymorphic base class

  void getInfo(std::string hName)
  { name = hName; }

  void showInfo() const
  {
    std::cout << "Your name is: " << name << '\n';
    std::cout << "And you are a " << getGenderString() << std::endl;
  }
};


class Man : public Human
{
protected:
  virtual std::string getGenderString() const
  { return "MAN"; }
};


class Woman : public Human
{
protected:
  virtual std::string getGenderString() const
  { return "WOMAN"; }
};


int main(){
    //local variables
    std::string choice;
    std::string tName;
    //declaring objects 
    Human *person = NULL;
    //user interface
    std::cout << "Please enter you name: ";
    std::cin >> tName;
    std::cout << "Are you a [boy/girl]: ";
    std::cin >> choice;
    //if handler
    if (choice == "boy"){
        person = new Man();
    }else if(choice == "girl"){
        person = new Woman();
    }
    person->getInfo(tName);
    person->showInfo();
    system("pause");
    delete person;
    return 0;
}

The above code uses a pure virtual function (one which has to be implemented in a derived class) to get the appropriate gender string. Everything else is common to both genders, so it's in the base class.

Note that there's a lot of good practice which could be added to the code, but I didn't want to confuse the issue too much. I didn't know if you have access to C++11 features, so I didn't use any. Your best bet for turning the above (working) code into good code is picking up a good C++ book.

다른 팁

At the moment Human class does represent both genders, which is not true in the real world. It should be rather the other way around: a Human class used as a base one, holding the name and delivering virtual methods which could be overridden in the Woman/Man classes, as it is in reality: adult :P human is either a man or a woman. The current design doesn't make much sense really.

Besides, name is a common property for both genders, same as the method operating on that, so they should go to the base class. You could go for template method design pattern, so eventually your code could be improved this way:

class Human
{
  std::string name;
  virtual std::string GetGender() const = 0;
public:
    // virtual d-tor

    Human(const std::string& humanName)
      : name(humanName) {}

    void showInfo() const 
    {
        std::cout << "Your name is: " << name << std::endl;
        std::cout << "And you are a " << GetGender() << std::endl;
    }
};

class Man : public Human{
  /*virtual*/ std::string GetGender() const { return "MAN"; }
public:
  Man(const std::string& name)
    : Human(name) {}
};

class Woman : public Human{
  /*virtual*/ std::string GetGender() const { return "WOMAN"; }
public:
  Woman(const std::string& name)
    : Human(name) {}
};

Then you could easily print the required properties when operating on the base class pointer pointing to the specific derived class:

humanObject->showInfo();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top