简体   繁体   中英

Multiple inheritance

I have 2 base classes (B1 and B2) which are derived from common Base class(B), where they have a common variable (let: int x; from base B), in 1st base x=0 , in the 2nd base x=10 (default values given in B1,B2 constructors).

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 derive one more class:

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

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

Here only one copy of x will be available as per virtual concept, now if I try to access x value with derived class object which instance of x I will get in O/p ( x=0 or x=10 ), and why?

In order to use virtual inheritance, base B must be declared as virtual in both B1 and B2 . Without that, you have non-virtual inheritance of B.

If you have non-virtual inheritance, then you have two B bases in D , so you can't access x in D without qualifying it as B1::x or B2::x

If you have virtual inheritance, then you only have one B and one x , so the two assignments to it ( x=0 and x=10 ) will happen in whichever order you did them in, and whichever one was later will overwrite the value set by the earlier one (much as with a simple variable x with two assignments).

In your setup as you have it, B is not actually inherited virtually, because you would have to declare virtual inheritance for B in both B1 and B2 (it always has to happen at the lowest level if the two "branches" are expected to be merged higher up in the class inheritance hierarchy), ie

class B1 : virtual public B
{
protected:

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

class B2 : virtual public B
{
protected:

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

If you do that, initialization of B would be completely different, because there are special rules for the construction of virtual base classes:

In virtual inheritance, the virtual base class is always initialized by the most derived class . Thus, as you have implemented the constructor of D as

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

and therefore don't call your B constructor explicitly, the compiler will assume that you want to call B s default constructor. But your class B does not have a default constructor, so you would 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 would have to do something like

class D : public B1, public B2
{
public:

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

and this also solves your question: The value of x will be whatever the most derived class wants it to be (99 in this case). Thus, there is no ambiguity.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM