初学者C ++问题:
我有一个Person类,该类具有受保护的变量FirstName和LastName:
class Person
{
protected:
int Id;
std::string FirstName;
std::string LastName;
public:
Person();
Person(std::string firstName, std::string lastName);
~Person();
std::string GetPersonInfo() const;
std::string GetFirstName() const;
std::string GetLastName() const;
};
inline std::string Person::GetPersonInfo() const {
return FirstName + " " + LastName;
}
inline std::string Person::GetFirstName() const {
return FirstName;
}
inline std::string Person::GetLastName() const {
return LastName;
}
我有一个从“人”(和成人班)继承的“老师”班
class Teacher :
public Person, public Adult
{
private:
int ClassroomID;
public:
Teacher() = default;
~Teacher() = default;
Teacher(std::string firstName, std::string lastName, std::string emailAddress, std::string phoneNumber,
std::vector<Address> teacherAddress, int classroomID);
};
在我的main()中,我有以下内容:
vector<Teacher> teachers = TeacherRepository.RetrieveTeachers();
for (Teacher teacher : teachers) {
cout << teacher.GetFirstName(); }
当我开始输入“老师”时。我看到“ GetFirstName”是一个选项。它会引发“ Teacher :: GetFirstName不明确”的编译器错误
我做错了什么?
编辑:成人的定义
class Adult :
public Person
{
protected:
std::string Email;
std::string PhoneNumber;
std::vector<Address> address;
public:
Adult() = default;
~Adult() = default;
Adult(std::string emailAddress, std::string phoneNumber, std::vector<Address> address);
Adult(std::string emailAddress, std::string phoneNumber);
};
答案 0 :(得分:1)
您的层次结构不正确。教师同时从“人”和“成人”继承,而“成人”也从“人”继承。在编写Teacher :: GetFirstName时,您希望编译器调用什么?也许Person :: GetFirstName或Adult :: Person :: GetFirstName。此外,您将具有Person变量的两个示例。
决定:
虚拟继承:
class Adult : virtual public Person {...};
class Teacher : virtual public Person, public Adult {...};
更多here
教师的基础班必须仅成人:
class Teacher : public Adult {...};
作为坏选项:您可以明确指出要调用的方法:
`Teacher t = ...;
t.Adult::GetFirstName();`
奖金:不要按值传递参数,在这种情况下,最好将参数作为常量引用传递。
`Person(const std::string& firstName, const std::string& lastName);`
相反
`Person(std::string firstName, std::string lastName);`
答案 1 :(得分:0)
您以前的设计中存在多个问题。导致编译错误的直接问题是Teacher
和Adult
类都继承了您的Person
。由于Adult
也是Person
的子类,因此这两个类都具有GetLastName()
方法,因此编译器无法确定要调用哪个方法。
更重要的是,您应该以更正确和清晰的方式管理层次结构。从语义上讲,成年人也应该是一个人,而老师应该是成年人。那么,为什么不只从Teacher
继承Adult
并在设计中使层次结构成为线性列表呢?
此外,如果您需要有关基类的完整信息,则应首先在派生类对象中初始化基类对象。使用C++ initialization list完成此操作。
class Person
{
protected:
int Id;
std::string FirstName;
std::string LastName;
public:
Person() = default;
Person(std::string firstName, std::string lastName) : FirstName(firstName), LastName(lastName) {}
~Person() = default;
std::string GetPersonInfo() const;
std::string GetFirstName() const;
std::string GetLastName() const;
};
inline std::string Person::GetPersonInfo() const {
return FirstName + " " + LastName;
}
inline std::string Person::GetFirstName() const {
return FirstName;
}
inline std::string Person::GetLastName() const {
return LastName;
}
class Adult : public Person
{
protected:
std::string Email;
std::string PhoneNumber;
std::vector<std::string> Address;
public:
Adult() = default;
~Adult() = default;
Adult(std::string firstName, std::string lastName, std::string emailAddress, std::string phoneNumber, std::vector<std::string> address)
: Person(firstName, lastName), Email(emailAddress), PhoneNumber(phoneNumber), Address(address) {};
Adult(std::string firstName, std::string lastName, std::string emailAddress, std::string phoneNumber)
: Person(firstName, lastName), Email(emailAddress), PhoneNumber(phoneNumber) {};
};
class Teacher : public Adult
{
private:
int ClassroomID;
public:
Teacher() = default;
~Teacher() = default;
Teacher(std::string firstName, std::string lastName, std::string emailAddress, std::string phoneNumber,
std::vector<std::string> teacherAddress, int classroomID)
: Adult(firstName, lastName, emailAddress, phoneNumber, teacherAddress), ClassroomID(classroomID) {}
};
int main(void) {
Teacher teacher("ExampleFirstName", "ExampleLastName", "example@email.com", "100-1001000", {"example address"}, 1);
cout << teacher.GetLastName() << endl;
return 0;
}