Home > OS >  Changing inherited class' member variables
Changing inherited class' member variables

Time:06-07

Background

I've been reading about inheritance and messing around with some code, and I'm trying to better understand how to implement virtual functions, and more broadly, how to change member variables in derived classes. Here's what I've got so far:

Code

#include <iostream>

class Base
{
private:
    int m_value {};
public:

    Base(int value = 5): m_value {value}
    {
    }

    int getValue()
    {
        return m_value;
    }

    virtual void add(int addend)
    {
        m_value = m_value   addend;
    }

};

class Derived: public Base
{
private:
    int m_value {};
public:

    Derived(int value = 5): m_value {value}
    {
    }

    virtual void add(int addend)
    {
        m_value = m_value   addend;
    }
};

int main()
{
    Derived derived {};

    std::cout << derived.getValue() << "\n";
    derived.add(2);
    std::cout << derived.getValue() << "\n";
    

return 0;
}

Problem

I want the inherited class to change its member variable when add() is called. Specifically, I was expecting derived.add(2) to make derived.m_value equal to 7 as opposed to 5. However, despite my efforts, I can't get derived.m_value to change.

What I've Tried

I reviewed a post that asked a similar question (Member function of inherited class won't change inherited base class variable), and so I added an overloaded assignment operator like this:

class Derived: public Base
{
private:
    int m_value {};
public:

    Derived(int value = 5): m_value {value}
    {
    }

    Derived& operator=(const Derived& derived)
    {
        m_value = derived.m_value;
        return *this;

    }

    void add(int addend)
    {
        m_value = m_value   addend;
    }

};

However, this addition and some other variations I tried still didn't work. It seems like I don't understand how inherited member functions interact with their member variables as well as I thought.

CodePudding user response:

Please find below your sample working the way you want. I'll explain below the code.

#include <iostream>

class Base
{
    protected: // HERE change n°1
        int m_value;

    public:
        Base(int value = 5) : m_value{ value }
        {
        }

        int getValue()
        {
            return m_value;
        }

        virtual void add(int addend)
        {
            m_value = m_value   addend;
        }
};

class Derived : public Base
{// HERE change n°2 : no more Derived::m_value which shadows the Base::m_value (this is due to the members of same name)
    public:

        Derived(int value = 5) : Base{ value } // HERE change n°3 : we build the parent class by calling it's constructor so Base::m_value is initialized
        {
        }

        void add(int addend) noexcept override // HERE change n°4
        {
            m_value = m_value   addend;
        }
};

int main()
{
    Derived derived{};

    std::cout << derived.getValue() << "\n";
    derived.add(2);
    std::cout << derived.getValue() << "\n";

    return 0;
}

Change n°1 : by setting the visibility of the member m_value to protected, it means we now have access to it in the child class. This is what you'd like to have in order to have common patterns/behaviour and stuff between class in an OOP point of view. If you set it private in your parent class, you'll NOT have access to it in the child class. This statement is valid for members and methods. For example, you may want to hide some internal management performed by the parent class.

Change n°2 : remove the declaration of m_value in the child class being given it shadows the Base::m_value as explained by Olaf.

Change n°3 : finally, we call the constructor of the Base class in the init list of the child class constructor, so the base instance is well constructed when you declare a derived variable in your main.

Change n°4 : you can add the override keywoard to the virtual methods you inherit. This is a tips to the compiler so it'll check the method signature is the same than the one in the parent class. This way, if you write a wrong method signature, or if you change your method in the parent class, you'll get an error/warning.

Hope it helps

  • Related