Section 11.3 created an employee class hierarchy, in which class BasePlusCommissionEmployee
inherited from class CommissionEmployee
. The Chapter 11 examples manipulated CommissionEmployee
and BasePlusCommissionEmployee
objects by using the objects’ names to invoke their member functions. We now examine the relationships among classes in a hierarchy more closely. The next several sections present a series of examples that demonstrate how base-class and derived-class pointers can be aimed at base-class and derived-class objects, and how those pointers can be used to invoke member functions that manipulate those objects.
• In Section 12.3.1, we assign the address of a derived-class object to a base-class pointer, then show that invoking a function via the base-class pointer invokes the base-class functionality in the derived-class object—i.e., the type of the handle determines which function is called.
• In Section 12.3.2, we assign the address of a base-class object to a derived-class pointer, which results in a compilation error. We discuss the error message and investigate why the compiler does not allow such an assignment.
• In Section 12.3.3, we assign the address of a derived-class object to a base-class pointer, then examine how the base-class pointer can be used to invoke only the base-class functionality—when we attempt to invoke derived-class member functions through the base-class pointer, compilation errors occur.
• Finally, in Section 12.3.4, we demonstrate how to get polymorphic behavior from base-class pointers aimed at derived-class objects. We introduce virtual
functions and polymorphism by declaring a base-class function as virtual
. We then assign the address of a derived-class object to the base-class pointer and use that pointer to invoke derived-class functionality—precisely the capability we need to achieve polymorphic behavior.
A key concept in these examples is to demonstrate that with public
inheritance an object of a derived class can be treated as an object of its base class. This enables various interesting manipulations. For example, a program can create an array of base-class pointers that point to objects of many derived-class types. Despite the fact that the derived-class objects are of different types, the compiler allows this because each derived-class object is an object of its base class. However, we cannot treat a base-class object as an object of any of its derived classes. For example, a CommissionEmployee
is not a BasePlusCommissionEmployee
in the hierarchy defined in Chapter 11—a CommissionEmployee
does not have a baseSalary
data member and does not have member functions setBaseSalary
and getBaseSalary
. The is-a relationship applies only from a derived class to its direct and indirect base classes.