14.2.1. Overloading the Output Operator <<

Image

Ordinarily, the first parameter of an output operator is a reference to a nonconst ostream object. The ostream is nonconst because writing to the stream changes its state. The parameter is a reference because we cannot copy an ostream object.

The second parameter ordinarily should be a reference to const of the class type we want to print. The parameter is a reference to avoid copying the argument. It can be const because (ordinarily) printing an object does not change that object.

To be consistent with other output operators, operator<< normally returns its ostream parameter.

The Sales_data Output Operator

As an example, we’ll write the Sales_data output operator:

ostream &operator<<(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " "
       << item.revenue << " " << item.avg_price();
    return os;
}

Except for its name, this function is identical to our earlier print function (§ 7.1.3, p. 261). Printing a Sales_data entails printing its three data elements and the computed average sales price. Each element is separated by a space. After printing the values, the operator returns a reference to the ostream it just wrote.

Output Operators Usually Do Minimal Formatting

The output operators for the built-in types do little if any formatting. In particular, they do not print newlines. Users expect class output operators to behave similarly. If the operator does print a newline, then users would be unable to print descriptive text along with the object on the same line. An output operator that does minimal formatting lets users control the details of their output.


Image Best Practices

Generally, output operators should print the contents of the object, with minimal formatting. They should not print a newline.


IO Operators Must Be Nonmember Functions

Input and output operators that conform to the conventions of the iostream library must be ordinary nonmember functions. These operators cannot be members of our own class. If they were, then the left-hand operand would have to be an object of our class type:

Sales_data data;
data << cout; // if operator<< is a member of Sales_data

If these operators are members of any class, they would have to be members of istream or ostream. However, those classes are part of the standard library, and we cannot add members to a class in the library.

Thus, if we want to define the IO operators for our types, we must define them as nonmember functions. Of course, IO operators usually need to read or write the nonpublic data members. As a consequence, IO operators usually must be declared as friends (§ 7.2.1, p. 269).


Exercises Section 14.2.1

Exercise 14.6: Define an output operator for your Sales_data class.

Exercise 14.7: Define an output operator for you String class you wrote for the exercises in § 13.5 (p. 531).

Exercise 14.8: Define an output operator for the class you chose in exercise 7.40 from § 7.5.1 (p. 291).


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

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