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. First letโ€™s focus on this one:
test.cpp:32:9: error: โ€˜std::string Person::m_nameโ€™ is private within this context
      32 |         m_name = name;
         |         ^~~~~~
That error is happening in the constructor of Student (line 32, 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. If we add a public Person::getName() function, we can call it in Student to access the name.
The other error messages focused on the constructor itself:
test.cpp: In constructor โ€˜Student::Student(std::string, int, std::string)โ€™:
test.cpp:31:49: error: no matching function for call to โ€˜Person::Person()โ€™
   31 |     Student(string name, int age, string major) {
      |                                                 ^
We saw a similar issue when exploring constructors and 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 automatically calls 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 call the Person constructor from the Student constructorโ€™s initialization list. To do so, we add : Person(name, age) after the constructor signature.
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โ€. Because we are making that call, the compiler wonโ€™t try to call the no-argument constructor for Person (which doesnโ€™t exist).
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.