some known problems (for example, Diamond problem).
First: There is no diamond pattern unless you explicitly create one.
class mixed: public B, public C
This will make mixed inherit from B and C. With each having their own explicit A (no diamond).
Since both B and C have virtual members derived from A it becomes ambiguous which one should be called but you have solved that by having explicit definitions of all virtuals in mixed
(so problem solved).
void mixed::f() { B::f();} // works fine.
Now even if you explicitly create a diamond.
Note: The diamond pattern does not appear normally. The diamond pattern is a design decision you must explicitly make and you use it to solve certain types of problem (by using virtual inheritance).
class B: public virtual A ...
class C: public virtual A ...
class mixed: public B, public C ...
You still don't have a problem. Because mixed::f()
only uses the B
branch (and then A). While mixed::g()
only uses the C
branch (and then A).
Even if A
has its own state (though that is probably a bad idea, usually best to use interfaces as a virtual base class) then we don't have a problem because mixed::f()
and mixed::g()
only call a function in one child (the problems start to occur if they call both sides and the state of A
is getting mutated by both calls.
Another solution could be composition.
That would also work.
class mixed: public A
{
B b;
C c;
public:
virtual void f() override {b.f();}
virtual void g() override {c.g();}
....
};
But what is the correct solution
There is no correct solution. That will depend a lot on the details that you have not mentioned (like what are the details of A).
BUT the general advice is to prefer composition over inheritance, but that is only general advice specifics will always boil down to the actual problem being solved.