Reputation: 2304
In most books and articles the only 'safe' (or at least the only advised) way of doing multiple inheritance is virtual inheritance with pure abstract base classes (which you could call virtual interfaces).
The reason is mostly stated as to avoid the Diamond Problem where one could create ambiguities for value of data members or for the implementation status of non-pure virtual functions.
Pure abstract base class don't suffer from both (no data members, no non-pure virtuals) and virtual inheritance even resolves the ambiguity of the actual memory address of the base class.
But given this explanation: If ambiguity only arises from forms of 'state' (e.g. data members, static function variables), then isn't a state-less non-abstract (maybe even with all 'final' methods) class equally safe to be the base class in a multiple inheritance hierarchy?
What possible problem am I missing?
PS: In case the answer is "If there is no virtual method, then you could use composition anyway": Besides the academic interest, I have a case where I need the property of member functions to be able to shadow free, global C-style functions, so I can't access them via a pointer-to-composition-object.
Upvotes: 4
Views: 145
Reputation: 40013
Virtual inheritance already achieves the desired safety by avoiding duplicate copies of non-static members. Variables and functions are the same in this regard: even if a base class is stateless, its non-static member functions are ambiguous if it is a base class more than once.
Virtual inheritance also handles overriding intelligently:
struct B {
virtual ~B()=default;
virtual void f()/*=0*/;
};
struct X : virtual B {};
struct Y : virtual B {
void f() override;
};
struct D : X,Y {};
B& b();
void g() {
b().f(); // calls Y::f
}
It doesn’t matter whether B::f
is pure-virtual or not.
So being stateless is not the important part. Moreover, if the base is stateless, having final
members would prevent the most obvious use case of default stub implementations. (The only other possibility would be to depend on the value of this
; otherwise the functions could be static.) So I wouldn’t necessarily encourage making a class stateless because it is intended for virtual inheritance (rather than simply because minimizing state is a generally good idea).
So you’re correct that non-pure-virtual functions can be safe, but that’s true even if the base is stateful. There are still limits to the safety of multiple inheritance, of course, like ambiguity if an overload set accepts multiple direct bases.
Upvotes: 1