14.3. Arithmetic and Relational Operators
Ordinarily, we define the arithmetic and relational operators as nonmember functions, as we do here with our Sales_item addition operator:
// assumes that both objects refer to the same isbn
Sales_item
operator+(const Sales_item& lhs, const Sales_item& rhs)
{
Sales_item ret(lhs); // copy lhs into a local object that we'll return
ret += rhs; // add in the contents of rhs
return ret; // return ret by value
}
Exercises Section 14.2.2
Exercise 14.9:Describe the behavior of the Sales_item input operator if given the following input:
Exercise 14.10:What is wrong with the following Sales_item input operator?
(a) 0-201-99999-9 10 24.95
(b) 10 24.95 0-210-99999-9
What would happen if we gave this operator the data in the previous exercise?Section 14.2.1 (p. 515). Be sure the operator handles input errors.
istream& operator>>(istream& in, Sales_item& s)
{
double price;
in >> s.isbn >> s.units_sold >> price;
s.revenue = s.units_sold * price;
return in;
}
The addition operator doesn't change the state of either operand; the operands are references to const objects. Instead, it generates and returns a new Sales_item object, which is initialized as a copy of lhs. We use the Sales_item compound-assignment operator to add in the value of rhs.


14.3.1. Equality Operators
Ordinarily, classes in C++ use the equality operator to mean that the objects are equivalent. That is, they usually compare every data member and treat two objects as equal if and only if all corresponding members are the same. In line with this design philosophy, our Sales_item equality operator should compare the isbn as well as the sales figures:
Exercises Section 14.3
Exercise 14.12:Write the Sales_item operators so that + does the actual addition and += calls +. Discuss the disadvantages of this approach compared to the way the operators were implemented in this section.Exercise 14.13:Which other arithmetic operators, if any, do you think Sales_item ought to support? Define those that you think the class should include.
The definition of these functions is trivial. More important are the design principles that these functions embody:If a class defines the == operator, it defines it to mean that two objects contain the same data.If a class has an operation to determine whether two objects of the type are equal, it is usually right to define that function as operator== rather than inventing a named operation. Users will expect to be able to compare objects using ==, and doing so is easier than remembering a new name.If a class defines operator==, it should also define operator!=. Users will expect that if they can use one operator, then the other will also exist.The equality and inequality operators should almost always be defined in terms of each other. One operator should do the real work to compare objects. The other should call the one that does the real work.
inline bool
operator==(const Sales_item &lhs, const Sales_item &rhs)
{
// must be made a friend of Sales_item
return lhs.units_sold == rhs.units_sold &&
lhs.revenue == rhs.revenue &&
lhs.same_isbn(rhs);
}
inline bool
operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
return !(lhs == rhs); // != defined in terms of operator==
}

14.3.2. Relational Operators
Chapter 15, we might want to use an associative container to hold Sales_item transactions. When we put objects into the container, we'd want them ordered by ISBN, and wouldn't care whether the sales data in two records were different.However, if we were to define operator< as comparison on isbn, that definition would be incompatible with the obvious definition of ==. If we had two transactions for the same ISBN, neither record would be less than the other. Yet, if the sales figures in those objects were different, then these objects would be !=. Ordinarily, if we have two objects, neither of which is less than the other, then we expect that those objects are equal.Because the logical definition of < is inconsistent with the logical definition of ==, it is better not to define < at all. We'll see in Chapter 15 how to use a separate named function to compare Sales_items when we want to store them in an associative container.
