The Overloaded << Operator

Most often, this book has used cout with the << operator, also called the insertion operator:

int clients = 22;
cout << clients;

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 operator in their names are used to overload operators, as discussed in Chapter 11, “Working with Classes.”) Thus, if you use a statement of the following form, and if value is one of the preceding types, a C++ program can match it to an operator function with the corresponding signature:

cout << value;

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 << " ";

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, is cinfully easy.)

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<<(type);

(Here, type is the type to be displayed.) The ostream & return type means that using this operator returns a reference to an ostream object. Which object? The function definitions say that the reference is to the object used to evoke the operator. In other words, an operator function’s return value is the same object that evokes the operator. For example, cout << "potluck" returns the cout object. That’s the feature that lets you concatenate output by using insertion. For example, consider the following statement:

cout << "We have " << count << " unhatched chickens. ";

The expression cout << "We have " displays the string and returns the cout object, reducing the statement to the following:

cout << count << " unhatched chickens. ";

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.

Image

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.174.23