C ++继承/多继承模棱两可的调用

时间:2018-07-18 19:55:46

标签: c++ inheritance multiple-inheritance

初学者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);

};

2 个答案:

答案 0 :(得分:1)

您的层次结构不正确。教师同时从“人”和“成人”继承,而“成人”也从“人”继承。在编写Teacher :: GetFirstName时,您希望编译器调用什么?也许Person :: GetFirstName或Adult :: Person :: GetFirstName。此外,您将具有Person变量的两个示例。

决定:

  1. 虚拟继承:

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

更多here

  1. 教师的基础班必须仅成人:

    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)

您以前的设计中存在多个问题。导致编译错误的直接问题是TeacherAdult类都继承了您的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;
}