Search code examples
c++oopinheritanceconstructorconstructor-chaining

Constructor chaining not using default values of class members?


I have two classes Unit and Archer. Archer inherits from unit. I tried to use constructor chaining to set the stats for the base class but the stats seem to be set to zero if I use the following code:

#include<iostream>

using namespace std;

class Unit{
    int damage = 0;
    int curHp = 0;
    int maxHp = 1;
    int range = 0;
    int cost = 0;

public:
    Unit(int _damage,int _maxHp,int _range,
         int _cost){
        damage = _damage;
        curHp = maxHp = _maxHp;
        range = _range;
        cost = _cost;
    }

    int getCost(){
        return cost;
    }
};

class Archer: public Unit{
    int damage = 25;
    int range = 50;
    int maxHp = 100;
    int cost = 150;
    int stepSize = 25;
    int returnedCoins = 0;
public:
    Archer():Unit(damage,maxHp,range,
                  cost){};
};

int main()
{
    Unit *curUnit =  new Archer();
    cout<< curUnit->getCost()<<endl;;
}

The output is 0.If I call Unit's construtor with a value instead of using cost(such as 25), I get the value instead I used. For some reason the base value I set in the archer class does not get used at all.

Also, I'm kind of new to OOP so I think I might be doing this the wrong way. I'd be happy if someone could show me the proper way to do this.


Solution

  • This is a non-starter

    class Archer: public Unit{
        int damage = 25;
        int range = 50;
        int maxHp = 100;
        int cost = 150;
        int stepSize = 25;
        int returnedCoins = 0;
    public:
        Archer():Unit(damage,maxHp,range,
                      cost){};
    };
    

    Bases are initialized before the members of your class. And speaking of which, you are duplicating the same members for no reason. Just pass those as arguments:

    class Archer: public Unit{
        int stepSize = 25;
        int returnedCoins = 0;
    public:
        Archer():Unit(25,100,50,
                      150){};
    };
    

    If your goal was to just give those values meaningful names, you can make them static class constants:

    class Archer: public Unit{
        static constexpr int damage = 25;
        static constexpr int range = 50;
        static constexpr int maxHp = 100;
        static constexpr int cost = 150;
    
        int stepSize = 25;
        int returnedCoins = 0;
    public:
        Archer():Unit(damage,maxHp,range,
                      cost){};
    };