Search code examples
c++inheritancevirtual

Join multiple, overlapping classes through overriding?


I was wondering about the following case, but I'm appearently missing the adequate terminology to find any answers anywhere.

Let's start with a common case: I have 3 classes in total. 2 of them inherit from the third one and are to be viewed as specializations.

Now those 3 classs are each still partly abstract and each introduce new pure virtual functions, because this "class structure" can be implemented in different ways for different purposes. And each of these 3 classes access the pure virtual functions from within, so they can not be implemented at a later time.

Then there is a 4th class, that inherits from the 2nd one, in order to specialize the purpose of the pure virtual functions of the 2nd class. There is a 5th class as well, which does the same for the 3rd class.

Now there are still pure virtual functions of the 1st class, which need specializiation according to and beffiting the 4th and 5th class. This is where I am having some issues and I could think of 2 ways to solve this, which don't really satisfy me.

  • Have a 6th class inherit from the 1st class and specialize it's purpose befitting to the needs of the 4th and 5th classes and have those classes inherit from the 6th class. This will lead to the "dreaded diamond".

enter image description here

  • Have a 6th class that does not inherit from the 1st class, but which implements the specialized purpose befitting the 4th and 5th class nevertheless. Then have the 4th class and 5th class inherit from the 6th and add an implementation of the pure virtual functions of the 1st class. These implementations do nothing else than call the analogous functions of the 6th, while passing the same parameters etc.

enter image description here

I'm currently tending to the second solution, since I want to avoid the "diamond dread". But I do not like the additional implementation code that comes with it. Isn't there an easier way to combine different (interfaces/)classes?

For example, using the second solution, I was thinking of something like having the same function prototypes in the 6th class as declared in the 1st class and than telling the compiler that the function of the 1st should be overridden by the function of the 6th class. Sadly, using myfunction; inside the class declaration of the 4th and 5th class does not work.

Or asked in general: Is there a way to join "interfaces" - which means that a pure virtual function of a class can be defined by an entirely different class, as long as the prototype is the same and for as long as they are both inherited from a child. I want to avoid duplicating code as much as possible, since I don't want "heavy" classes.

If this ilumination is too abstract, I will come up with an example.

€dit: Asking for your opinions: What would be the best solution in this case?


Solution

  • I would go with a solution that is pretty similar to the first one:

    1. Create the 6th class exactly as you described.
    2. Now use the Bridge design pattern - have an inner member in both 2 & 3 of type 1. Inject an instance of class 6 to this inner member.
    3. Create a tunnel implementation for the virtual methods you're missing in classes 4 & 5. The implementation should be a one-liner that just calls the concrete implementation from 6.

    Hope this helps. If you need more help I'll try to elaborate some more.

    ==============

    Following your comment, hope this helps:

    Well not exactly. Take the first solution and remove the inheritance of 6 from 4 & 5 (4 inherits 2 and 5 inherits 3 and that's it).

    Class 6 inherits 1. Let's call class 1 - Base. Add to both classes 4&5 a member of type Base (let's call it impl).

    Let's say class 4 is foo and class 2 is Base2. It will look something like (sorry for the bad c++ syntax, it's been a while since I've written actual c++ code):

    class foo: Base2
    { 
         private Base* impl; 
    
         public foo(Base* impl) { this.impl = impl; } 
    
         void virtualMethod() { 
                this.impl->virtualMethod() 
         } 
    }