Skip to main content

Section 19.6 Upcasting

Inheriting members and calling code from a base class are one major way inheritance allows us to reuse existing code. The other major way is by allowing us to treat a derived object as if it was a member of a base class.
Consider line 8 in the sample below. It creates personRef2, which is a reference to a Person, but then assigns it to reference a Student:
Listing 19.6.1.
This works because according to the concept of inheritance, the Student is-a Person. A Person reference (or pointer) can refer (point) to a Student because a Student is just a specialized version of Person. Anytime we are working with a Student, it must also be true we are working with a Person.
The opposite is not true. Although a Person may happen to be a Student, there is a distinction between the two. A Person does not necessarily have the properties or behaviors of a Student. This version of the code tries to make a Student& that refers to a Person. But doing so is a compile error because it makes no sense::
Listing 19.6.2.
This ability to upcast and treat a derived class object as if it were a base class object enables us to write a function that can work on any type of Person. In this sample, we call makeIntroduction twice. Once with a plain Person and then with a Person that happens to be a Student:
Listing 19.6.3.
Without inheritance, we would need to write separate functions for each of the data types. However, there is an issue with the resulting output. Notice how the Alex object introduces itself. It uses the basic Person version of introduce(), not the customized Student version that includes the Student’s major.
This is because while compiling the makeIntroduction function, the compiler needs to decide what introduce() to call. And it needs to generate one version of the code that will work for all possible types of Person. The only reasonable thing to do in that case is for the compiler to treat makeIntroduction as if it was written:
void makeIntroduction(const Person& person) {
    cout << "Let's meet: " << person.getName() << endl;
    person.Person::introduce(); // call Person version of introduce
}
We probably would prefer makeIntroductions to not treat Student objects exactly the same as Person objects by using the customized version of .introduce(). But to do that, we need to tell C++ to wait until runtime to decide which version of introduce() to call. Which we will learn to do next.

Checkpoint 19.6.1.

Which is the correct statement about upcasting?
  • Upcasting allows a derived class object to be treated as a base class object.
  • Upcasting allows a base class object to be treated as a derived class object.
You have attempted of activities on this page.