In C++, what is a virtual base class?

后端 未结 11 2353
一个人的身影
一个人的身影 2020-11-22 00:55

I want to know what a \"virtual base class\" is and what it means.

Let me show an example:

class Foo
{
public:
    void DoSomething() { /* .         


        
11条回答
  •  野性不改
    2020-11-22 01:21

    About the memory layout

    As a side note, the problem with the Dreaded Diamond is that the base class is present multiple times. So with regular inheritance, you believe you have:

      A
     / \
    B   C
     \ /
      D
    

    But in the memory layout, you have:

    A   A
    |   |
    B   C
     \ /
      D
    

    This explain why when call D::foo(), you have an ambiguity problem. But the real problem comes when you want to use a member variable of A. For example, let's say we have:

    class A
    {
        public :
           foo() ;
           int m_iValue ;
    } ;
    

    When you'll try to access m_iValue from D, the compiler will protest, because in the hierarchy, it'll see two m_iValue, not one. And if you modify one, say, B::m_iValue (that is the A::m_iValue parent of B), C::m_iValue won't be modified (that is the A::m_iValue parent of C).

    This is where virtual inheritance comes handy, as with it, you'll get back to a true diamond layout, with not only one foo() method only, but also one and only one m_iValue.

    What could go wrong?

    Imagine:

    • A has some basic feature.
    • B adds to it some kind of cool array of data (for example)
    • C adds to it some cool feature like an observer pattern (for example, on m_iValue).
    • D inherits from B and C, and thus from A.

    With normal inheritance, modifying m_iValue from D is ambiguous and this must be resolved. Even if it is, there are two m_iValues inside D, so you'd better remember that and update the two at the same time.

    With virtual inheritance, modifying m_iValue from D is ok... But... Let's say that you have D. Through its C interface, you attached an observer. And through its B interface, you update the cool array, which has the side effect of directly changing m_iValue...

    As the change of m_iValue is done directly (without using a virtual accessor method), the observer "listening" through C won't be called, because the code implementing the listening is in C, and B doesn't know about it...

    Conclusion

    If you're having a diamond in your hierarchy, it means that you have 95% probability to have done something wrong with said hierarchy.

提交回复
热议问题