AymenTM
AymenTM

Reputation: 569

C++: For a class that inherited multiple classes, how to inherit certain attributes from one class and others from the other?

Can someone help me understand how a class that inherits from multiple classes can retain certain attribute values from one class and other certain attribute values from another.

(and how would one do so for certain functions as well)


Here is a bit of code to describe the problem.

It's a situation where there is a diamond inheritance structure:


------------- Base

----------/---------------\

-------/--------------------\

--- Mother-------------Father

---\ -----------------------/

------\ ------------------/

---------\ -------------/

------------ Child


The goal is to inherit from both the Father class & the Mother class (& evidently from the Base class) but to retain the y value of the Father and the z value from the Mother. I just don't know how to do that.

I believe that the problem with the following code is that the order in which the constructors are called make it so that the Father constructor overwrites the z value that the Mother constructor right before it initialized.

I'm thinking that I might have to make a special private/protected Father constructor that doesn't initialize the z and a special private/protected Mother constructor that doesn't initialize the y and explicitly call those constructors.

But idk if that's the right way of doing it or if there's a better way. Does anyone know a better way ?


#include <iostream>

class Base {

    protected:

        int x;
        int y;
        int z;

    public:

        Base(void) : x(0) {}

};

/* — — — — — — — — — — — — — — — — — — — —  */

class Father
    : public virtual Base {

    public:

        Father(void) : Base() {
            y = 1;
            z = 1;
        }
};

/* — — — — — — — — — — — — — — — — — — — —  */

class Mother
    : public virtual Base {

    public:

        Mother(void) : Base() {
            y = 2;
            z = 2;
        }
};

/* — — — — — — — — — — — — — — — — — — — —  */

class Child
    : public Mother, public Father {

    public:

        Child(void) : Base() {

            y = Father::y;
            z = Mother::z;
        }

        int getX() { return x; };
        int getY() { return y; };
        int getZ() { return z; };
};

/* — — — — — — — — — — — — — — — — — — — —  */

int main() {

    Child newborn;

    std::cout << newborn.getX() << std::endl
              << newborn.getY() << std::endl
              << newborn.getZ() << std::endl;

    return (0);
}

/* — — — — — — — — — — — — — — — — — — — —  */


Output:

0
1
1

——— VS ———

Desired Output:

0
1
2

Upvotes: 2

Views: 6257

Answers (1)

Fareanor
Fareanor

Reputation: 6805

You can't do it this way.

The virtual inheritance is aimed to not duplicate the members.

Knowing this:

  • Child::x, Mother::x and Father::x are exactly the same variable
  • Child::y, Mother::y and Father::y are exactly the same variable
  • Child::z, Mother::z and Father::z are exactly the same variable

These are just three ways to access the same variable on the memory stack. So when you writes y = Father::y;, it is exactly the same as if you had written y = y;, and so on for the other variables.


If you really want to do that without changing your design, perhaps you can store in Father and in Mother an extra variable which contains the preset you want and just give it to Child through scope resolution.

Father, Mother and Child could look like:

class Father : public virtual Base
{
    protected:
        int preset;

    public:
        Father() : preset(1)
        {
            y = preset;
            z = preset;
        }
};

class Mother : public virtual Base
{
    protected:
        int preset;

    public:
        Mother() : preset(2)
        {
            y = preset;
            z = preset;
        }
};

class Child : public Mother, public Father
{
    public:
        Child()
        {
            y = Father::preset;
            z = Mother::preset;
        }

        int getX() const {return x;}
        int getY() const {return y;}
        int getZ() const {return z;}
};

And it should do the trick with few changes.


To conclude, I would say that for each problem that requires multiple inheritance, there is at least one other solution (a better design) which does not imply multiple inheritance (This is only my opinion).

So I would advise you to reconsider your design instead of using the workaround I proposed here.

Upvotes: 3

Related Questions