Skip to main content

Section 19.3 Access Modifiers and Inheritance

Our previous example of inheritance ignored encapsulation, one of the big ideas of OOP, by making all of the members public.
Let’s try to fix that by making the member variables private and adding public constructors. Here is a first attempt. Scroll down to see the error message and the explanation of what is going wrong.
Listing 19.3.1.
Trying to run that code produces a cascading mess of errors. But the key ones to pay attention to are the ones that look like this:
test.cpp:25:9: error: β€˜std::string Person::m_name’ is private within this context
      25 |         m_name = name;
         |         ^~~~~~
That error is happening in the constructor of Student (highlighted in the code). Even though the Student class inherits from Person it cannot access the private members of Person. Recall that private is enforced at the class level, not for individual objects. One Person can access the private members of another Person, but a Student cannot access the private members of a Person (even though Student is-a Person).
This means that although the Student has an m_name, it can’t access it! We can only directly access public members of Person.

Insight 19.3.1.

Think back to the memory diagram on the previous page (FigureΒ 19.2.3). Inheritance means there is a Person inside of the Student object. That is different than a Student getting its own copy of all the members of a Personβ€”a Student does not have a m_name.
One way to fix this is to do what we would with composition - to rely on public functions to access Person variables from Student. TIf we add a public Person::getName() function, we can call it in Student to access the name.
The other error messages above were focused on the constructor itself:
test.cpp: In constructor β€˜Student::Student(std::string, int, std::string)’:
test.cpp:24:49: error: no matching function for call to β€˜Person::Person()’
   24 |     Student(string name, int age, string major) {
      |                                                 ^
This is the same issue we had with composition. The constructor for Student needs to set up the Person part of the object. Since we have not said how to do that, the compiler tries to automatically call the no-argument constructor for Person. But we don’t have a no-argument constructor for Person. So we get an error.
To fix this, we need to add a constructor to Person that takes the name and age as arguments. Then we can call that constructor from the Student constructor’s initialization list.
This version of the code has both of those fixes:
Listing 19.3.2.
The : Person(name, age) on line 30 says β€œcall the constructor of the base class Person with the arguments name and age”. That means the code will not try to call the no-arg Person() constructor since we have specified how to initialize the base class. And it means that we don’t have to try to set the inherited private variables from inside Student.
Then, on line 35, we can use a public getter to access the name from the Person object.

Checkpoint 19.3.1.

Which is the true statement?
  • Derived classes inherit public members and can access them.
  • Derived classes inherit public members but cannot access them.
  • Derived classes do not inherit public members.

Checkpoint 19.3.2.

Which is the true statement?
  • Derived classes inherit private members and can access them.
  • Derived classes inherit private members but cannot access them.
  • Derived classes do not inherit private members.

Checkpoint 19.3.3.

We are writing a class Button that inherits from Input. The Input class has a private member variable string m_id and a constructor Input(string id). A Button will add a string m_text and a string m_color. Build the code for Button.
You have attempted of activities on this page.