In C++, as in C, by default the << operator is used as the bitwise left-shift operator (see Appendix E, “Other Operators”). An expression such as x<<3 means to take the binary representation of x and shift all the bits three units to the left. Obviously, this doesn’t have a lot to do with output. But the ostream class redefines the << operator through overloading to output for the ostream class. In this guise, the << operator is called the insertion operator instead of the left-shift operator. (The left-shift operator earned this new role through its visual aspect, which suggests a flow of information to the left.) The insertion operator is overloaded to recognize all the basic C++ types:
• unsigned char
• signed char
• char
• short
• unsigned short
• int
• unsigned int
• long
• unsigned long
• long long (C++11)
• unsigned long long (C++11)
• float
• double
• long double
The ostream class provides a definition for the operator<<() function for each of these data types. (Functions that have
cout <<
For example, the expression cout << 88 matches the following method prototype:
ostream & operator<<(int);
Recall that this prototype indicates that the operator<<() function takes one type int argument. That’s the part that matches the 88 in the previous statement. The prototype also indicates that the function returns a reference to an ostream object. That property makes it possible to concatenate output, as in the following old rock hit:
cout << "I'm feeling sedimental over " << boundary << "\n";
If you’re a C programmer who has suffered through C’s multitudinous % type specifiers and the problems that arise when you mismatch a specifier type to a value, using cout is almost sinfully easy. (And C++ input, of course,
Output and Pointers
The ostream class defines insertion operator functions for the following pointer types:
• const signed char *
• const unsigned char *
• const char *
• void *
C++ represents a string, don’t forget, by using a pointer to the location of the string. The pointer can take the form of the name of an array of char or of an explicit pointer-to-char or of a quoted string. Thus, all the following cout statements display strings:
char name[20] = "Dudly Diddlemore";
char * pn = "Violet D'Amore";
cout << "Hello!";
cout << name;
cout << pn;
The methods use the terminating null character in the string to determine when to stop displaying characters.
C++ matches a pointer of any other type with type void * and prints a numeric representation of the address. If you want the address of the string, you have to type cast it to another type, as shown in the following code fragment:
int eggs = 12;
char * amount = "dozen";
cout << &eggs // prints address of eggs variable
cout << amount; // prints the string "dozen"
cout << (void *) amount; // prints the address of the "dozen" string
Output Concatenation
All the incarnations of the insertion operator are defined to return type ostream &. That is, the prototypes have this form:
ostream & operator<<(
(Here,
cout << "We have " << count << " unhatched chickens.\n";
The expression cout << "We have " displays the string and returns the cout object, reducing the statement to the following:
cout << count << " unhatched chickens.\n";
Then the expression cout << count displays the value of the count variable and returns cout, which can then handle the final argument in the statement (see Figure 17.4). This design technique really is a nice feature, which is why the examples of overloading the << operator in the previous chapters shamelessly imitate it.
Figure 17.4. Output concatenation.
The Other ostream Methods
Besides the various operator<<() functions, the ostream class provides the put() method for displaying characters and the write() method for displaying strings.
Originally, the put() method had the following prototype:
ostream & put(char);
The current standard is equivalent, except it’s templated to allow for wchar_t. You invoke it by using the usual class method notation:
cout.put('W'); // display the W character