Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
240 views
in Technique[技术] by (71.8m points)

c++ - When virtual inheritance IS a good design?

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...