Home > Enterprise >  Make a child class inherit specific attributes from two different parent classes?
Make a child class inherit specific attributes from two different parent classes?

Time:07-21

I have a problem with a Diamond inheritance exercise.

I have one base class A. Here is its constructor :

A::A(std::string name) : _hp(10), _ep(10), _ad(0)
{
    std::cout << "A object created !" << std::endl;
    return ;
}

Then, I have two parent classes B and C. Here are their constructors:

B::B(std::string name) : A(name)
{

    std::cout << "B object created !" << std::endl;
    this->_hp = 100;
    this->_ep = 50;
    this->_ad = 20;
    return;
}

C::C(std::string name) : A(name)
{
    std::cout << "C object created !" << std::endl;
    this->_hp = 100;
    this->_ep = 100;
    this->_ad = 30;
    return ;
}

And finally, I have one child class . Here is its constructor:

D::D(std::string name) : A(name   "_comes_from_A")
{
    this->_name = name;
    std::cout << "D object created !" << std::endl;
    this->_hp = C::_hp;
    this->_ep = B::_ep;
    this->_ad = C::_ad;
    return;
}

The D class inherits from class B and C. The B and C classes both inherits from class A. I did something like this :

class A
{
    // code here

    protected:

    std::string _name;
    int         _hp;
    int         _ep;
    int         _ad;
};

class B : virtual public A
{
    // code here
};

class C : virtual public A
{
    // code here
};

class D : public B, public C
{
    // code here
};

As it can be noticed in the constructor of D class, I want it to inherits _ep from the B class (50) and _hp and _ad from the C class (100 and 30).

However, if I check the value of the _ep value in my D class, (with something like this for instance) :

std::cout << "ENERGY POINTS " << this->_ep << std::endl;

it is always equal to 100 (which comes from the C class).

I have noticed it depends on the order in which I handle inheritance for D class but I would like to be able to access values of any of the parent class from my child class. Can someone help me with that ? Thanks in advance!

MINIMAL REPRODUCIBLE EXAMPLE :

class A
{
    public :

    A(){
        return ;
    };
    A(std::string name) : _hp(10), _ep(10), _ad(0){
        std::cout << "A object created !" << std::endl;
        return ;
    };
    ~A(){
        std::cout << "A object " << this->_name << " destroyed." << std::endl;
        return ;
    };

    protected:

    std::string _name;
    int         _hp;
    int         _ep;
    int         _ad;
};

class B : virtual public A
{
    public :

    B(){
        return ;
    };
    B(std::string name) : A(name){
        std::cout << "B object created !" << std::endl;
        this->_hp = 100;
        this->_ep = 50;
        this->_ad = 20;
        return ;
    };
    ~B(){
        std::cout << "B object " << this->_name << " destroyed." << std::endl;
        return ;
    };
};

class C : virtual public A
{
    public :

    C(){
        return ;
    };
    C(std::string name) : A(name){
        std::cout << "C object created !" << std::endl;
        this->_hp = 100;
        this->_ep = 100;
        this->_ad = 30;
        return ;
    };
    ~C(){
         std::cout << "C object " << this->_name << " destroyed." << std::endl;
    return ;
    };
};

class D : public B, public C
{
    public :

    D(){
        return ;
    };
    D(std::string name) : A(name   "_comes_from_a"){
        this->_name = name;
        std::cout << "D object created !" << std::endl;
        this->_hp = C::_hp;
        this->_ep = B::_ep;
        this->_ad = C::_ad;
        std::cout << "HIT POINTS " << this->_hp << std::endl;
        std::cout << "ENERGY POINTS " << this->_ep << std::endl;
        std::cout << "ATTACK DAMAGE " << this->_ad << std::endl;
        return;
     }
     ~D(){
        std::cout << "D object " << this->_name << " destroyed." << std::endl;
        return ;
     };
};

int main(void)
{
     D  obj_D("TEST");
     return (0);
}

CodePudding user response:

Okay, I got my program to work properly. Maybe I didn't explain well what I wanted to do, but I'm posting my solution here.
There are 4 classes A, B, C and D. They all have _hp, _ep and _ad variables.
D inherits from B AND C, which in turn inherit from A.
         A
       /     \
      B     C
       \      /
          D
I wanted my D class to take :

  • _ep value from the B class
  • _hp and _ad values from the C class

Here is the minimal reproducible example of the code that worked for me :

# include <iostream>
# include <string>

class A
{
    public :

        A(){
            return ;
        };

        A(std::string name) : _hp(10), _ep(10), _ad(0){
            std::cout << "A object created !" << std::endl;
            return ;
        };

        ~A(){
            std::cout << "A object " << this->_name << " destroyed." << std::endl;
            return ;
        };

    protected:

        std::string _name;
        int         _hp;
        int         _ep;
        int         _ad;
};

class B : virtual public A
{
    public :

        B(){
            return ;
        };

        B(std::string name) : A(name){
            std::cout << "B object created !" << std::endl;
            this->_hp = 100;
            this->_ep = 50;
            this->_ad = 20;
            return ;
        };

        ~B(){
            std::cout << "B object " << this->_name << " destroyed." << std::endl;
            return ;
        };

        static const int    EP = 50;
};

class C : virtual public A
{
    public :

        C(){
            return ;
        };

        C(std::string name) : A(name){
            std::cout << "C object created !" << std::endl;
            this->_hp = 100;
            this->_ep = 100;
            this->_ad = 30;
            return ;
        };

        ~C(){
            std::cout << "C object " << this->_name << " destroyed." << std::endl;
            return ;
        };

        static const int    HP = 100;
        static const int    AD = 30;
};

class D : public B, public C
{
    public :

        D(){
            return ;
        };
        D(std::string name) : A(name   "_comes_from_a"){
            this->_name = name;
            std::cout << "D object created !" << std::endl;
            this->_hp = C::HP;
            this->_ep = B::EP;
            this->_ad = C::AD;
            std::cout << "HIT POINTS " << this->_hp << std::endl;
            std::cout << "ENERGY POINTS " << this->_ep << std::endl;
            std::cout << "ATTACK DAMAGE " << this->_ad << std::endl;
            return;
        }

        ~D(){
            std::cout << "D object " << this->_name << " destroyed." << std::endl;
            return ;
        };
};

int main(void)
{
    D   obj_D("TEST");
    return (0);
}

The difference with the example that I posted in the question is that I declared static const int variables (HP, EP and AD) in my B and C classes. Thus, I am now able to access the values either from B or C classes in the constructor of class D. Typically, what I did earlier was wrong :

    // before (not working)
    this->_hp = C::_hp;
    this->_ep = B::_ep;
    this->_ad = C::_ad;   

    // now (working)
    this->_hp = C::HP;
    this->_ep = B::EP;
    this->_ad = C::AD;

The output is now :

A object created !
D object created !
HIT POINTS 100
ENERGY POINTS 50
ATTACK DAMAGE 30
D object TEST destroyed.
C object TEST destroyed.
B object TEST destroyed.
A object TEST destroyed.
  • Related