Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

multiple inheritance - 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.

question from:https://stackoverflow.com/questions/55829798/c-diamond-problem-how-to-call-base-method-only-once

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...