Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ : Multiple inheritance with polymorphism

(pardon the noob question in advance)

I have 4 classes:

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

Essentially Person is the base class, which are directly subclassed by both Student and Employee. StudentEmployee employs multiple inheritance to subclass both Student and 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}; 

When I use an array of Person, the base class, I can put Person and all of its subclasses inside this array. Except for StudentEmployee, given the reason ambiguous base class.

Given that StudentEmployee is guaranteed to have all the methods and attributes of Person, is StudentEmployee considered a subclass of Person?

  • If so, Why does the compiler not allow me to assign an object to a variable of the type of its superclass?
  • If not, why not; and what would be the proper way to accomplish this?

Cheers


EDIT: Preemptively, this question is NOT the same as either of the following:
polymorphism relates inheritance
Inheritance mucking up polymorphism in C++?

like image 629
bguiz Avatar asked Aug 22 '10 10:08

bguiz


1 Answers

StudentEmployee certainly is a subclass of Person. The problem is it is so twice: It indirectly inherits Person twice (once through Student and once through Employee) and that's why you get the "ambiguous base class" error. To make sure StudentEmployee only inherits Person once, you have to use virtual inheritance, like so:

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

This will fix your error.

There is another big problem with your code, though, and it's called slicing.

When you do this:

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

An array of three Person objects will be created but those objects will be copy constructed using the implicitly defined copy constructor of the Person class. Now, the problem with this is that the objects in your array will be just Person objects and not objects of the subclasses you want them to be.

To fix this, you'll have to make an array of pointers to Person objects, like this:

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

or

Person* ppl[] = {&pat, &sam, &em, &sen};
like image 168
mtvec Avatar answered Oct 11 '22 15:10

mtvec