使代码更小以进行多重继承

时间:2014-02-08 21:17:22

标签: c++ class multiple-inheritance derived-class

我写了一个非常小的程序,你输入的是你是男孩还是女孩,并打印出一个声明。我的主要问题是,从我的代码中可以看出,除了从基类复制和粘贴之外,还有更简单的女性写作方式。 这是我的代码

#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;
}

当我尝试从课程Woman派生课程Man时,会使person.getInfo(tName)person.showInfo()模糊不清。这是为什么?我怎样才能使这些代码更小(对于女性来说)。

2 个答案:

答案 0 :(得分:3)

你已经倒退 - 公共继承代表 IS-A 关系。所以你的用法是说“每个人都是男人,而每个人都是女人。”这不起作用。公共继承永远不会被用作“在一个地方获得所有功能”的便利。这就是构成(或者最坏的情况下,非公共继承)的用途。

但是,您的情况是使用继承的一个很好的例子。它必须遵循其自然的定义(每个人人;每个女人人类)。也就是说,使Human成为基类并在那里实现所有共享功能。像这样:

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

上面的代码使用纯虚函数(必须在派生类中实现的函数)来获取适当的性别字符串。其他一切对于两种性别都是共同的,所以它在基类中。

请注意,有很多好的做法可以添加到代码中,但我不想过多地混淆这个问题。我不知道你是否可以访问C ++ 11的功能,所以我没有使用任何功能。将上述(工作)代码转换为良好代码的最佳选择是选择good C++ book

答案 1 :(得分:0)

目前,人类确实代表了两种性别,这在现实世界中是不正确的。它应该是另一种方式:一个人类被用作基础,持有名称并提供可以在女人/男人类中被覆盖的虚拟方法,因为它实际上是:成人:P人类要么是男人还是女人目前的设计确实没有多大意义。

此外,name是两个性别的公共属性,与操作它的方法相同,因此它们应该转到基类。您可以使用模板方法设计模式,因此最终可以通过以下方式改进您的代码:

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

然后,当操作指向特定派生类的基类指针时,您可以轻松地打印所需的属性:

humanObject->showInfo();