Niklas Niklas - 1 month ago 14
C++ Question

Ambiguous workaround for multiinheritance?

I have a base class called animal, and a dog and a cat that inherit from Animal.
And a multiinheritance class called dogcat, that inherit from dog and cat,
in Animal i have method called sleep. When i want to use that method from dogcat, i get the error "DogCat::sleep" is ambiguous, i do understand the problem, but i read in a book that it should be possible, when you declare sleep as virtual - but it does not work.

Is this not possible is the book wrong or is there any workaround?

class Animal
{
public:
Animal(){}

virtual void sleep()
{
cout << "zzzzzzzzz" << endl;
}
virtual void eat() = 0;

};

class Dog: public Animal
{
protected:
Dog(){}

virtual void eat() override
{
cout << "eats dogfood" << endl;
}
};

class Cat :public Animal
{
public:
Cat(){}
virtual void eat() override
{
cout << "eats catfood" << endl;
}
};

class DogCat : public Dog, public Cat
{
public:
DogCat(){}
using Dog::eat;

};

int main(int argc, char** argv) {
DogCat *DC = new DogCat();
DC->sleep();//Error
}

Answer

You have the diamond problem

enter image description here

The "diamond problem" (sometimes referred to as the "deadly diamond of death"[4]) is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If there is a method in A that B and C have overridden, and D does not override it, then which version of the method does D inherit: that of B, or that of C?

So. Now you have two instances of A. What is it the solution? You have two:

  1. Define sleep operation in one of subclases and call it:
class Cat :public Animal
{
    public:
        Cat(){}
        virtual void eat() override
        {
            cout << "eats catfood" << endl;
        }

        void sleep()
        {
            Animal::sleep();
        }
};

int main(int argc, char** argv) {
    DogCat *DC = new DogCat();
    DC->Cat::sleep();
}
  1. Use virtual inheritance like says @Asesh answer. The problem is the common method eat(). You have to override it.