c++ inheritance/multi-inheritance 模棱两可的调用
c++ inheritance/multi-inheritance ambiguous call
初学者 C++ 问题:
我有一个 class 人保护变量 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;
}
我有一个继承自 Person 的 Teacher class(还有一个 Adult Class)
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(); }
当我开始输入 "teacher." 时,我看到 "GetFirstName" 作为一个选项出现;它会引发 "Teacher::GetFirstName is ambiguous"
的编译器错误
我做错了什么?
编辑:成人定义
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);
};
您的层次结构不正确。 Teacher 同时继承了 Person 和 Adult,Adult 也继承了 Person。当你写 Teacher::GetFirstName 时,你希望编译器调用什么?也许 Person::GetFirstName 或 Adult::Person::GetFirstName。此外,您将有两个 Person 变量的示例。
决定:
虚拟继承:
class Adult : virtual public Person {...};
class Teacher : virtual public Person, public Adult {...};
更多here
老师的基本class必须是仅限成人:
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);`
您之前的设计存在多个问题。导致编译错误的直接问题是你的 Teacher
是从 Adult
和 Person
class 继承的。由于 Adult
也是 Person
的子 class,因此这两个 class 都有 GetLastName()
方法,因此编译器无法判断调用哪一个。
更重要的是,您应该以更正确和清晰的方式管理您的层次结构。从语义上讲,成人也应该是人,老师也应该是成人。那么,为什么不仅从 Adult
继承 Teacher
,并使您的层次结构成为设计中的线性列表?
此外,如果您想要基本 classes 的完整信息,您应该首先在派生 class 对象中初始化基本 class 对象。使用 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;
}
初学者 C++ 问题:
我有一个 class 人保护变量 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;
}
我有一个继承自 Person 的 Teacher class(还有一个 Adult Class)
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(); }
当我开始输入 "teacher." 时,我看到 "GetFirstName" 作为一个选项出现;它会引发 "Teacher::GetFirstName is ambiguous"
的编译器错误我做错了什么?
编辑:成人定义
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);
};
您的层次结构不正确。 Teacher 同时继承了 Person 和 Adult,Adult 也继承了 Person。当你写 Teacher::GetFirstName 时,你希望编译器调用什么?也许 Person::GetFirstName 或 Adult::Person::GetFirstName。此外,您将有两个 Person 变量的示例。
决定:
虚拟继承:
class Adult : virtual public Person {...}; class Teacher : virtual public Person, public Adult {...};
更多here
老师的基本class必须是仅限成人:
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);`
您之前的设计存在多个问题。导致编译错误的直接问题是你的 Teacher
是从 Adult
和 Person
class 继承的。由于 Adult
也是 Person
的子 class,因此这两个 class 都有 GetLastName()
方法,因此编译器无法判断调用哪一个。
更重要的是,您应该以更正确和清晰的方式管理您的层次结构。从语义上讲,成人也应该是人,老师也应该是成人。那么,为什么不仅从 Adult
继承 Teacher
,并使您的层次结构成为设计中的线性列表?
此外,如果您想要基本 classes 的完整信息,您应该首先在派生 class 对象中初始化基本 class 对象。使用 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;
}