EDIT3: Please be sure to clearly understand what I am asking before answering (there are EDIT2 and lots of comments around). There are (or were) many answers which clearly show misunderstanding of the question (I know that's also my fault, sorry for that)
Hi, I've looked over the questions on virtual inheritance (class B: public virtual A {...}
) in C++, but did not find an answer to my question.
I know that there are some issues with virtual inheritance, but what I'd like to know is in which cases virtual inheritance would be considered a good design.
I saw people mentioning interfaces like IUnknown
or ISerializable
, and also that iostream
design is based on virtual inheritance. Would those be good examples of a good use of virtual inheritance, is that just because there is no better alternative, or because virtual inheritance is the proper design in this case? Thanks.
EDIT: To clarify, I'm asking about real-life examples, please don't give abstract ones. I know what virtual inheritance is and which inheritance pattern requires it, what I want to know is when it is the good way to do things and not just a consequence of complex inheritance.
EDIT2: In other words, I want to know when the diamond hierarchy (which is the reason for virtual inheritance) is a good design
If you have an interface hierarchy and a corresponding implementation hierarchy, making the interface base classes virtual bases is necessary.
E.g.
struct IBasicInterface
{
virtual ~IBasicInterface() {}
virtual void f() = 0;
};
struct IExtendedInterface : virtual IBasicInterface
{
virtual ~IExtendedInterface() {}
virtual void g() = 0;
};
// One possible implementation strategy
struct CBasicImpl : virtual IBasicInterface
{
virtual ~CBasicImpl() {}
virtual void f();
};
struct CExtendedImpl : virtual IExtendedInterface, CBasicImpl
{
virtual ~CExtendedImpl() {}
virtual void g();
};
Usually this only makes sense if you have a number of interfaces that extend the basic interface and more than one implementation strategy required in different situations. This way you have a clear interface hierarchy and your implementation hierarchies can use inheritance to avoid the duplication of common implementations. If you're using Visual Studio you get a lot of warning C4250, though.
To prevent accidental slicing it is usually best if the CBasicImpl
and CExtendedImpl
classes aren't instantiable but instead have a further level of inheritance providing no extra functionality save a constructor.