Search code examples
c++multiple-inheritancediamond-problem

C++ diamond problem - How to call base method only once


I'm using multiple inheritance in C++ and extending base methods by calling their base explicitly. Assume the following hierarchy:

     Creature
    /        \
 Swimmer    Flier
    \        /
       Duck

Which corresponds to

class Creature
{
    public:
        virtual void print()
        {
            std::cout << "I'm a creature" << std::endl;
        }
};

class Swimmer : public virtual Creature
{
     public:
        void print()
        {
            Creature::print();
            std::cout << "I can swim" << std::endl;
        }
};

class Flier : public virtual Creature
{
     public:
        void print()
        {
            Creature::print();
            std::cout << "I can fly" << std::endl;
        }
};

class Duck : public Flier, public Swimmer
{
     public:
        void print()
        {
            Flier::print();
            Swimmer::print();
            std::cout << "I'm a duck" << std::endl;
        }
};

Now this presents a problem - calling the duck's print method calls its respective base methods, all of which in turn call the Creature::print() method, so it ends up being called twice-

I'm a creature
I can fly
I'm a creature
I can swim
I'm a duck

I would like to find a way to make sure the base method is called only once. Something similar to the way virtual inheritance works (calling the base constructor on the first call, then only assigning a pointer to it on successive calls from other derived classes).

Is there some built-in way to do this or do we need to resort to implementing one ourselves?

If so, how would you approach this?

The question isn't specific to printing. I wondered if there's a mechanism for extending base methods and functionality while keeping the call order and avoiding the diamond problem.

I understand now that the most prominent solution would be to add helper methods, but I just wondered if there's a "cleaner" way.


Solution

  • You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:

    class Swimmer : public virtual Creature
    {
         public:
            // Virtually inherit from Creature::print and extend it by another line of code
            void print() : virtual Creature::print()
            {
                std::cout << "I can swim" << std::endl;
            }
    };
    
    class Flier : public virtual Creature
    {
         public:
            // Virtually inherit from Creature::print and extend it by another line of code
            void print() : virtual Creature::print()
            {
                std::cout << "I can fly" << std::endl;
            }
    };
    
    class Duck : public Flier, public Swimmer
    {
         public:
            // Inherit from both prints. As they were created using "virtual function inheritance",
            // this will "mix" them just like in virtual class inheritance
            void print() : Flier::print(), Swimmer::print()
            {
                std::cout << "I'm a duck" << std::endl;
            }
    };
    

    So the answer to your question

    Is there some built-in way to do this?

    is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...