operator<<
and operator>>
are frequently overloaded for new classes. On their own, these functions are pretty simple once you learn the basic pattern. But when used in an inheritance hierarchy, especially when chained together, some unusual syntax is required. Fortunately, there is also a pattern that we can learn that makes overloading these functions in the presence of inheritance fairly straightforward.
All three inserter operators are presented below follow the operator<<
the pattern outlined previously. All three are friend
functions, return an ostream
reference, have an ostream
reference for the first argument, and have a reference to the defining class as the second argument. But Actor and Star add something new, which is highlighted in the following figure.
Person |
friend ostream& operator<<(ostream& out, Person& me) { out << me.name << endl; return out; } |
|
---|---|---|
Actor |
friend ostream& operator<<(ostream& out, Actor& me) { out << (Person &)me << " " << me.agent << endl; return out; } |
|
Star |
friend ostream& operator<<(ostream& out, Star& me) { out << (Actor &)me << " " << me.balance << endl; return out; } |
ostream
reference, so the compiler matches a function call to the corresponding function based on the second parameter (i.e., the right-hand operand).
A Star is an Actor and an Actor is a Person. So, a Star object has a balance and, by inheritance, an agent and a name. If a program prints a Star object, it should print all three data members. However, the inherited members are private
in the two sperclasses, and the Star object can't access their members directly; it must use their public interfaces, operator<<. So, our goal is to create a chain of function calls:
The highlighted casting operations form expressions that convert a Star reference into an Actor reference, and an Actor reference into a Person reference. Following the cast, the expression matches the second or right-hand operand of the << operator (i.e., the expression matches the second argument in the superclass operator<< function). The sequence of chained function calls begins when the Star operator<< function is called. The numbers indicate the order in which action is performed: