Consider the Rational class (header file)   --   the whole thing: rat2.h

In the Rational class, you saw operator overloading. For example, consider the basic arithmetic operators:
Rational operator+(const Rational &) const;
Rational operator-(const Rational &) const;
Rational operator*(const Rational &) const;
Rational operator/(const Rational &) const;
In the sample Rational main program you saw that   5 + x didn't compile, giving an error that no code was given to allow adding a Rational object to an int.

An alternative way to overload these operators is to make them global instead of member functions (similar to operator<<). Typically you would include them in a similar manner to the overloaded operator<< and operator>>. The .h file would include the prototypes:
friend Rational operator+(const Rational &, const Rational &);
friend Rational operator-(const Rational &, const Rational &);
friend Rational operator*(const Rational &, const Rational &);
friend Rational operator/(const Rational &, const Rational &);
They now have two parameters since in a statement such as   z = x + y;   both x and y are passed in. Notice that there is no const at the end since they are not member functions.

The code for these routines is typically still found in the .cpp file and is similar to the member function except you need to remember to always qualify (put the object in front of the dot) all computations involving members. For example, compare the member operator+
Rational Rational::operator+(const Rational& a) const {
Rational sum;
sum.numerator = a.numerator * denominator + a.denominator * numerator;
sum.denominator = a.denominator * denominator;
sum.reduce();
return sum;
}
with the nonmember operator+
Rational operator+(const Rational& leftop, const Rational& rightop) {
Rational sum;
sum.numerator = rightop.numerator * leftop.denominator
+ rightop.denominator * leftop.numerator;
sum.denominator = rightop.denominator * leftop.denominator;
sum.reduce();
return sum;
}