Search code examples
c++multiple-inheritancevirtual-functionsoverridingvirtual-inheritance

Most derived class cannot compile if virtual function not implemented, but can compile if one base class does not implement the virtual function


I have a C++ program with 4 classes : Person, Student, Employee, and PartTimeStudent.

Student and Employee each derive from Person, and PartTimeStudent derives from all 3 classes (making it the most derived class). Person, Student, and Employee also have a derived function called VDescribe().

Please see the code below :

class Person
{
    ...    
    virtual void VDescribe();
    ...
};

class Student : virtual public Person
{
    ...    
    virtual void VDescribe();
    ...
};

class Employee : virtual public Person
{
    ...    
    virtual void VDescribe();
    ...
};

class PartTimeStudent : virtual public Person,
    virtual public Student,
    virtual public Employee
{
    ...
};

Note : In the code snippet above I have omitted the Constructors, Destructors and member variables because they are not relevant to the problem at hand.

When I try to compile the code, I get the following errors :

override of virtual function "Person::VDescribe" is ambiguous

'PartTimeStudent': ambiguous inheritance of 'void Person::VDescrive(void)'

'PartTimeStudent': ambiguous inheritance of 'void Person::VDescribe(void)'

However, this only occurs if both Student and Employee implement VDescribe(). If one of the classes does not implement VDescribe(), compilation is successful. I still get warnings though, e.g. the following warnings occur if I omit VDescribe() from Employee :

'PartTimeStudent': inherits 'Student::Student::VDescribe' via dominance

May I ask why this occurs? I would like to know why PartTimeStudent is unable to compile if all 3 classes implement VDescribe(), but if either Student or Employee does not have the function, PartTimeStudent is still compilable.


Solution

  • Two overrides

    Imagine the scanario where Student and Employee implement VDescribe, while PartTimeStudent does not implement it. How would you expect this code to behave:

    PartTimeStudent pts;
    pts.VDescribe();
    

    Which implementation of VDescribe should be called? It's ambiguous, which is precisely why the compilation errors out.

    One override

    When Employee does not override VDescribe, the situation is a bit different. PartTimeStudent then has the following functions to inherit:

    • Person::VDescribe overridden by Student::VDescribe, coming via Student
    • Person::VDescribe not overridden, coming via Employee.
    • Person::VDescribe not overridden, coming via Person.

    In this situation, Student::VDescribe overrides Person::VDescribe and is an unambiguous overrider, so the compiler is able to use it. However, it is warning you that there was an alternative inheritance path which did not go through this override. This warning is not very useful in practice, and is one of the few warning I routinely disable.


    If you want your code to compile also in the case when both Student and Employee override VDescribe, you actually have to override it in PartTimeStudent too. The function will then have an unambiguous final overrider and the code will compile just fine. You can call one or both of the inherited implementations using qualified names. Example:

    void PartTimeStudent::VDescribe()
    {
      Student::VDescribe();
      if (isWorking()) Employe::VDescribe();
    }