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 变量的示例。

决定:

  1. 虚拟继承:

    class Adult : virtual public Person {...}; class Teacher : virtual public Person, public Adult {...};

更多here

  1. 老师的基本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 是从 AdultPerson 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;
}