I have an abstract base class which acts as an interface.
I have two "sets" of derived classes, which implement half of the abstract class. ( one "set" defines the abstract virtual methods related to initialization, the other "set" defines those related to the actual "work". )
I then have derived classes which use multiple inheritance to construct fully defined classes ( and does not add anything itself ).
So: ( bad pseudocode )
class AbsBase {
virtual void init() = 0;
virtual void work() = 0;
}
class AbsInit : public AbsBase {
void init() { do_this(); }
// work() still abs
}
class AbsWork : public AbsBase {
void work() { do_this(); }
// init() still abs
}
class NotAbsTotal : public AbsInit, public AbsWork {
// Nothing, both should be defined
}
First of all, can I do this? Can I inherit from two classes which are both derived from the same Base? (I hope so).
Here is the "real problem", though (I lied a bit above to simplify the example).
What I have really gone and done is add non abstract accessors methods to the base class:
class AbsBase {
public:
void init() { init_impl(); }
void work() { work_impl(); }
private:
virtual void init_impl() = 0;
virtual void work_impl() = 0;
}
Because, a common idiom is to make all virtual methods private.
Unfortunately, now both AbsInit, and AbsWork inherit these methods, and so NotAbsTotal inherits "two of each" ( I realize I may be butchering what is really happening at compile time ).
Anyway, g++ complains that: "request for member init() is ambiguous" when trying to use the class.
I assume that, had I used my AbsBase class as a pure interface, this would have been avoided ( assuming that the top example is valid ).
So:
- Am I way off with my implementation?
- Is this a limitation of the idiom of making virtual methods private?
- How do I refactor my code to do what I want? ( Provide one common interface, but allow a way to swap out implementations for "sets" of member functions )
Edit:
Seems I am not the first one:
http://en.wikipedia.org/wiki/Diamond_problem
Seems Virtual Inheritance is the solution here. I have heard of virtual inheritance before, but I have not wrapped my head around it. I am still open to suggestions.
See Question&Answers more detail:
os