You can input and output fundamental-type data using the stream extraction operator >>
and the stream insertion operator <<
, respectively. The C++ class libraries overload these binary operators for each fundamental type, including pointers and char *
strings. You can also overload these operators to perform input and output for your own types. The program of Figs. 10.3–10.5 overloads these operators to input PhoneNumber
objects in the format
(555) 555-5555
and to output them in the format
Area code: 555
Exchange: 555
Line: 5555
(555) 555-5555
The program assumes telephone numbers are input correctly.
The stream extraction operator function operator>>
(Fig. 10.4, lines 20–28) takes the istream
reference input
and the PhoneNumber
reference number
as arguments and returns an istream
reference. The function inputs phone numbers of the form (555)
555-5555
into objects of class PhoneNumber
. When the compiler sees the expression
cin >> phone
in line 15 of Fig. 10.5, the compiler generates the non-member function call
operator>>(cin, phone);
When this call executes, reference parameter input
(Fig. 10.4, line 20) becomes an alias for cin
and reference parameter number
becomes an alias for phone
.
The operator function reads as string
s the three parts of the telephone number into the areaCode
(line 22), exchange
(line 24) and line
(line 26) data members of the PhoneNumber
object referenced by parameter number
—the function is a friend of the class, so it can access a PhoneNumber
’s private
members. Stream manipulator setw
limits the number of characters read into each string
. When used with cin
and string
s, setw
restricts the number of characters read to the number of characters specified by its argument (i.e., setw(3)
allows three characters to be read). The parentheses, space and dash characters are skipped by calling istream
member function ignore
(Fig. 10.4, lines 21, 23 and 25), which discards the specified number of characters in the input stream (one character by default).
Function operator>>
returns istream
reference input
(the alias for cin
). This enables input operations on PhoneNumber
objects to be cascaded with input operations on other PhoneNumber
objects or other data types. For example, a program can input two PhoneNumber
objects in one statement as follows:
cin >> phone1 >> phone2;
First, the expression cin
>>
phone1
executes by making the non-member function call
operator>>(cin, phone1);
This call then returns a reference to cin
as the value of cin
>>
phone1
, so the remaining portion of the expression is interpreted as cin
>>
phone2
. This executes by making the non-member function call
operator>>(cin, phone2);
Overloaded operators should mimic the functionality of their built-in counterparts—e.g., the +
operator should perform addition, not subtraction. Avoid excessive or inconsistent use of operator overloading, as this can make a program cryptic and difficult to read.
The stream insertion operator function (Fig. 10.4, lines 10–16) takes an ostream
reference (output
) and a const
PhoneNumber
reference (number
) as arguments and returns an ostream
reference. Function operator<<
displays objects of type PhoneNumber
. When the compiler sees the expression
cout << phone
in line 21 of Fig. 10.5, the compiler generates the non-member function call
operator<<(cout, phone);
Function operator<<
displays the parts of the telephone number as string
s, because they’re stored as string
objects. To prove that the stream extraction operator read the individual pieces of a PhoneNumber
properly, function operator<<
displays each data member separately, then displays a properly formatted phone number.
friend
FunctionsThe functions operator>>
and operator<<
are declared in PhoneNumber
as non-member, friend
functions (Fig. 10.3, lines 10–11). They’re non-member functions because the object of class PhoneNumber
must be the operator’s right operand. If these were to be PhoneNumber
member functions, the following awkward statements would have to be used to output and input a PhoneNumber
, respectively:
phone << cout;
phone >> cin;
Such statements would be confusing to most C++ programmers, who are familiar with cout
and cin
appearing as the left operands of these operators. Overloaded operator functions for binary operators can be member functions only when the left operand is an object of the class in which the function is a member.
Overloaded input and output operators are declared as friends
if they need to access non-public
class members directly for performance or because the class may not offer appropriate get functions. Also, the PhoneNumber
reference in function operator<<
’s parameter list (Fig. 10.4, line 10) is const
, because the function simply outputs a PhoneNumber
, and the PhoneNumber
reference in function operator>>
’s parameter list (line 20) is non-const
, because the function must modify the PhoneNumber
object to store the telephone number.
New input/output capabilities for user-defined types are added to C++ without modifying standard input/output library classes. This is another example of C++’s extensibility.
The overloaded stream insertion operator (<<
) is used in an expression in which the left operand has type ostream&
, as in cout
<<
classObject
. To use the operator in this manner where the right operand is an object of a user-defined class, it must be overloaded as a non-member function. To be a member function, operator <<
would have to be a member of class ostream
. This is not possible for user-defined classes, since we are not allowed to modify C++ Standard Library classes. Similarly, the overloaded stream extraction operator (>>
) is used in an expression in which the left operand has the type istream&
, as in cin
>>
classObject
, and the right operand is an object of a user-defined class, so it, too, must be a non-member function. Also, each of these overloaded operator functions may require access to the private
data members of the class object being output or input, so these overloaded operator functions can be made friend
functions of the class for performance reasons.