Multiple inheritance

I have 2 base classes (B1 and B2) that are derived from a common base class (B) where they have a common variable (let's say: int x;

from base B), in 1st base x=0

, in 2nd base x=10

(values โ€‹โ€‹by defaults are given in constructors B1, B2).

Visually:

class B
{
    int x;

protected:

    B(int x) : x{x}{}
};

class B1 : public B
{
protected:

    B1() : B(0){}
};

class B2 : public B
{
protected:

    B2() : B(10){}
};

      

Now if I get another class:

class D : virtual public B1, virtual public B2
{
public:

    D() : B1{}, B2{}{}
};

      

Here only one copy of x will be available according to the virtual concept, now if I try to access the value of x with a derived class, I get an instance of x in O / p ( x=0

or x=10

), and why?

+3


source to share


2 answers


To use virtual inheritance, base B

must be declared virtual in B1

both B2

. Without that, you have non-virtual inheritance B.

If you have non-virtual inheritance you have two bases B

in D

, so you cannot access x

in D

without getting it as B1::x

orB2::x



If you have virtual inheritance, you have only one B

and one x

, therefore, two assignments to him ( x=0

and x=10

) will be performed in any order in which you do them, and whichever one later will overwrite the value set by an earlier ( as with a simple variable x

with two assignments).

+5


source


In your setup, as you have, B

it is not actually inherited in practice, because you need to declare virtual inheritance for B

both in B1

and in B2

(this should always happen at the lowest level if two "branches" are expected to merge above in the class inheritance hierarchy), i.e.

class B1 : virtual public B
{
protected:

    B1() : B(0){}
};

class B2 : virtual public B
{
protected:

    B2() : B(10){}
};

      

If you do this, the initialization B

will be completely different, as there are special rules for building virtual base classes:

In virtual inheritance, the virtual base class is always initialized with the most derived class. Thus, since you have implemented the constructor D

as

D() : B1(), B2(){}

      

and hence not calling the constructor explicitly B

, the compiler assumes that you want to call the default constructor B

. But your class B

doesn't have a default constructor, so you'll get a compiler error like this:



prog.cpp: In constructor โ€˜D::D()โ€™:
prog.cpp:31:20: error: no matching function for call to โ€˜B::B()โ€™
     D() : B1(), B2(){}
                    ^

      

Therefore, you will need to do something like

class D : public B1, public B2
{
public:

    D() :  B(99), B1(), B2(){}
};

      

and that also solves your question: the value x

will be what this class wants (in this case 99). Thus, there is no ambiguity.

PS: You can also see, your question is at the heart of why it makes sense to have a special rule about constructing a virtual base class from the most derived class.

+2


source







All Articles