C ++: множественное наследование с полиморфизмом - PullRequest
13 голосов
/ 22 августа 2010

(заранее извините за вопрос noob)

У меня есть 4 класса:

class Person {};
class Student : public Person {};
class Employee : public Person {};
class StudentEmployee : public Student, public Employee {};

По существу Person - это базовый класс, который непосредственно подклассируется как Student, так иEmployee.StudentEmployee использует множественное наследование для подкласса Student и Employee.

Person pat = Person("Pat");
Student sam = Student("Sam");
Employee em = Employee("Emily");
StudentEmployee sen = StudentEmployee("Sienna");


Person ppl[3] = {pat, sam, em};
//compile time error: ambiguous base class
//Person ppl[4] = {pat, sam, em, sen}; 

Когда я использую массив Person, базовый класс, я могу поместить Person и все егоподклассы внутри этого массива.За исключением StudentEmployee, учитывая причину неоднозначного базового класса.

Учитывая, что StudentEmployee гарантированно имеет все методы и атрибуты Person, считается ли StudentEmployee подклассом Person?

  • Если так, то почему компилятор не позволяет мне назначать объект переменной типа его суперкласса?
  • Если нет, то почему бы и нет;и каков будет правильный способ сделать это?

Приветствия


РЕДАКТИРОВАТЬ: К сожалению, этот вопрос не совпадает с одним из следующих:
полиморфизм относится к наследованию
Наследование наследует полиморфизм в C ++?

Ответы [ 2 ]

14 голосов
/ 22 августа 2010

StudentEmployee определенно является подклассом Person.Проблема в том, что он дважды : он косвенно наследует Person дважды (один раз через Student и один раз через Employee), и поэтому вы получаете ошибку "неоднозначный базовый класс".Чтобы убедиться, что StudentEmployee наследует только Person один раз, вы должны использовать виртуальное наследование , например:

class Person {};
class Student : public virtual Person {};
class Employee : public virtual Person {};
class StudentEmployee : public Student, public Employee {};

Это исправит вашу ошибку.

Однако есть еще одна большая проблема с вашим кодом, и она называется нарезка .

Когда вы делаете это:

Person ppl[3] = {pat, sam, em};

Массивиз трех Person объектов будут созданы, но эти объекты будут созданы с использованием неявно определенного конструктора копирования класса Person.Теперь проблема в том, что объекты в вашем массиве будут просто Person объектами, а не объектами подклассов, которые вы хотите, чтобы они были.

Чтобы это исправить, вам придется создать массивуказателей на Person объектов, например:

Person* ppl[] = {new Person("Pat"), new Student("Sam"),
                 new Employee("Emily"), new StudentEmployee("Sienna")};

или

Person* ppl[] = {&pat, &sam, &em, &sen};
3 голосов
/ 22 августа 2010

Существует два одинаково возможных пути от объекта типа StudentEmployee до Person.

Необходимо использовать ключевое слово virtual для классов Student и Employee.См. FAQ 25.8 Фактически, пройдите весь этот раздел.

...