Professional C__ - Marc Gregoire [103]
SpreadsheetCell myCell(4), aThirdCell(2);
aThirdCell -= myCell;
aThirdCell += 5.4;
Code snippet from OperatorOverloading\SpreadsheetCellTest.cpp
You cannot, however, write code like this (which is a good thing!):
5.4 += aThirdCell;
Overloading Comparison Operators
The comparison operators, such as >, <, and ==, are another useful set of operators to define for your classes. Like the basic arithmetic operators, they should be global friend functions so that you can use implicit conversion on both the left-hand side and right-hand side of the operator. The comparison operators all return a bool. Of course, you can change the return type, but we don’t recommend it. Here are the declarations and definitions:
class SpreadsheetCell
{
public:
// Omitted for brevity
friend bool operator==(const SpreadsheetCell& lhs,
const SpreadsheetCell& rhs);
friend bool operator<(const SpreadsheetCell& lhs,
const SpreadsheetCell& rhs);
friend bool operator>(const SpreadsheetCell& lhs,
const SpreadsheetCell& rhs);
friend bool operator!=(const SpreadsheetCell& lhs,
const SpreadsheetCell& rhs);
friend bool operator<=(const SpreadsheetCell& lhs,
const SpreadsheetCell& rhs);
friend bool operator>=(const SpreadsheetCell& lhs,
const SpreadsheetCell& rhs);
// Omitted for brevity
};
Code snippet from OperatorOverloading\SpreadsheetCell.h
bool operator==(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.mValue == rhs.mValue);
}
bool operator<(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.mValue < rhs.mValue);
}
bool operator>(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.mValue > rhs.mValue);
}
bool operator!=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.mValue != rhs.mValue);
}
bool operator<=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.mValue <= rhs.mValue);
}
bool operator>=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return (lhs.mValue >= rhs.mValue);
}
Code snippet from OperatorOverloading\SpreadsheetCell.cpp
The preceding overloaded operators are working with mValue, which is a double. Most of the time, performing equality or inequality tests on floating point values is not a good idea. You should use an epsilon test, but this falls outside the scope of this book.
In classes with more data members, it might be painful to compare each data member. However, once you’ve implemented == and <, you can write the rest of the comparison operators in terms of those two. For example, here is a definition of operator>= that uses operator<:
bool operator>=(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
return !(lhs < rhs);
}
You can use these operators to compare SpreadsheetCells to other SpreadsheetCells, and to doubles and ints:
if (myCell > aThirdCell || myCell < 10) {
cout << myCell.getValue() << endl;
}
Code snippet from OperatorOverloading\SpreadsheetCellTest.cpp
Building Types with Operator Overloading
Many people find the syntax of operator overloading tricky and confusing, at least at first. The irony is that it’s supposed to make things simpler. As you’ve discovered, that doesn’t mean simpler for the person writing the class, but simpler for the person using the class. The point is to make your new classes as similar as possible to built-in types such as int and double: It’s easier to add objects using + than to remember whether the method name you should call is add() or sum().
Provide operator overloading as a service to clients of your class.
At this point, you might be wondering exactly which operators you can overload. The answer is “almost all of them — even some you’ve never heard of.” You have actually just scratched the surface: You’ve seen the assignment operator in the section on object life cycles, the basic arithmetic operators, the shorthand arithmetic operators, and the comparison operators. Overloading the stream insertion and extraction operators is also useful.