Hey,
I have a little design issue and i hope you can help me out with this.
I have 3 interfaces defined:
1 2 3 4 5 6 7 8 9 10 11 12 13
class IBase
{
public:
virtualvoid methodIBase() = 0;
};
class IDerivedA : public IBase
{
};
class IDerivedB : public IBase
{
};
Now if i implement them:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class Base : public IBase
{
public:
void methodIBase();
};
class DerivedA : public IDerivedA, public Base
{
//methodIBase not implemented by Base
};
class DerivedB : public IDerivedB, public Base
{
//methodIBase not implemented by Base
};
The problem is, that the method implemented by Base isn't recognized to be implemented in the derived classes.
If this is is only 1 method defined in Base, the overhead of implementing the method in the derived classes as well and then call the base function is minimal. But in my IBase class there are a lot of methods and I have many classes deriving from it, so I would have to implement all these methods for every single class then.
I googled this problem and found out that there is no solution for implementing an interface with a Base class.
But is there a better way to do this by design?
This is an example of what's known as the Diamond of Death. Basically, DerivedA inherits twice from IBase, One of those IBase derivations (via Base) implements methodIBase, while the other (via IDerivedA) doesn't.
You can fix this using virtual inheritance. I recommend reading up on multiple inheritance for a more detailed explanation, and to learn how to do this.
If you used virtual sub-classing, you get rid of the problem, and you get a diamond.
So if you have:
1 2 3 4
class IBase;
class IDerivedA : public IBase;
class Base : public IBase;
class DerivedA : public IDerivedA, public Base;
then IBase is included twice in DerivedA's ancestry. Obviously the compiler will not know which member functions and variables to use, and should complain.
But if you add the virtual keyword there will be only one:
1 2 3 4
class IBase;
class IDerivedA : virtualpublic IBase;
class Base : virtualpublic IBase;
class DerivedA : virtualpublic IDerivedA, virtualpublic Base;
Exactly how far up the tree you need to go with the 'virtuals' I'm not sure, but a compiler will soon tell you.
'public virtual' and 'virtual public' are identical.