c++inheritancedatamember

Why is my inherited method outputting Base class' member instead of derived class' member


I am trying to print the member 'age' from the Mum class which inherits the method print_age() from Dad, but it is printing the member 'age' from Dad's class

#include <iostream>
#include <string>

using namespace std;

int main()
{

  class Dad
  {
  protected:
    int age = 59;

  public:
    void print_age() { cout << age << endl; }
  };

  class Mum : public Dad
  {
  protected:
    int age = 54;
  };

  Mum m;
  m.print_age();
}

This outputs 59 when I want it to output 54


Solution

  • In C++, only member functions can be overridden, not member variables. As a result, when you write

      class Mum : public Dad
      {
      protected:
        int age = 54;
      };
    

    C++ interprets this as "I know that Dad already has an int field called age whose value is 59, but I'd like to also add a different int field called age whose value is 59 and that only lives in the Mum class." Stated differently, you aren't replacing the old value of age with a new one; you're declaring a new variable that Dad doesn't know about that coincidentally has the same name as one of the variables from Dad.

    Now, why does that mean that you see the value 59? Let's look at the code for Dad:

      class Dad
      {
      protected:
        int age = 59;
    
      public:
        void print_age() { cout << age << endl; }
      };
    

    In print_age, C++ sees the use of age and then needs to decide what to do. It has no idea that there's a Mum class that will be defined later that will also independently create a protected int called age. Rather, it sees age defined in Dad and says "oh, that must be what age refers to" and uses that value. As a result, when you call

       m.print_age();
    

    you see the value of age in Dad rather than the value of age in Mum. It's because the code for print_age is written in the Dad class, which can't see anything in Mum.

    If you'd like to make it so that Mum has age 59, you could do this instead:

      class Mum : public Dad
      {
      public:
         Mum() {
            age = 54;
         }
      };
    

    Here, the constructor says "when you create a Mum object, go find the age data member and set it equal to 54." This means that there's one single age variable, which defaults to 59 but is explicitly set to 54 in the Mum constructor. Now, calling print_age will print out 54 because the code for Dad::print_age looks at the age variable that was just set.

    Hope this helps!