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
:
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::
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:
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.
You have attempted of activities on this page.