我写了一个非常小的程序,你输入的是你是男孩还是女孩,并打印出一个声明。我的主要问题是,从我的代码中可以看出,除了从基类复制和粘贴之外,还有更简单的女性写作方式。 这是我的代码
#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()
模糊不清。这是为什么?我怎样才能使这些代码更小(对于女性来说)。
答案 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();