In C++, polymorphism lets a variable refer to objects of different data types. The only catch is that the different data types must be members of the same inheritance hierarchy and they must be lower in the hierarchy than the variable's data type. The cool part is this ability lets the same instruction behave differently, based on the actual object's data type instead of the variable's data type.
Consider the hierarchy of the UML class diagram in Figure 1. Here, I have derived the Manager and Salesperson classes from the Employee class. This lets me use an Employee pointer to point to an Employee, Manager, or Salesperson object.
The following code is an attempt at polymorphism:
Employee* pEmp = new Manager; cout << *pEmp << endl;
However, this attempt fails since the code does not invoke the Manager's insertion operator (<<) as I intendedit invokes the Employee's insertion operator. This happens because the indirection operation (*) is performed first, so *pEmp returns the data type of the pointer. In this case, because pEmp is an Employee pointer, the *pEmp operation returns the Employee data type in spite of pointing to a Manager object. After *pEmp is done, the function call is matched using the Employee data type. Consequently, the Employee's insertion function is matched and not the Manager's function as intended.
In C++, polymorphism normally requires virtual methods. Because only methods can be inherited, many programmers think the insertion (<<) and extraction (>>) operators cannot display polymorphic behavior because these operators are implemented as nonmember friend functions. However, there are several ways of making these operators polymorphic. In this article, I compare and contrast three different techniques.