C ++: множественное наследование с полиморфизмом

(заранее прошу прощения за вопрос новичка)

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

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

Essentially Person - это базовый класс, который непосредственно подклассы Студент и Сотрудник . 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 ++?

13
задан Community 23 May 2017 в 12:07
поделиться

2 ответа

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};
14
ответ дан 1 December 2019 в 23:46
поделиться

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

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

3
ответ дан 1 December 2019 в 23:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: