Operator Overloading Extra
Operator Overloading Extra
arithmetic operators: +, -, *, /, %
relational operators: <, <=, ==, !=, >, >=
assignment operator: =
logical operators: &&, ||, !
input/output operators: <<, >>
1
The Thee ways
Member function
The first way is by class method (member function). This is the most popular
way.
2
(m2.dollar * 100 + m2.cent);
Money local(diff);
return local;
}
3
int thistotal = m1.getDollars() * 100 + m1.getCents();
int m2total = m2.getDollars() * 100 + m2.getCents();
return (thistotal < m2total);
}
Friend function
private:
int dollar;
int cent;
};
// no keyword "friend" in the function definition
ostream& operator<<(ostream& out, const Money & m)
{
out << "$" << m.dollar // dollar private in m -- OK
<< "." << m.cent; // cent private in m -- OK
return out;
}
m.dollar = static_cast<int>(moneyAsDouble);
m.cent = static_cast<int>(moneyAsDouble * 100) % 100;
return in;
}
4
friend functions vs. member functions
An operator is just a function. This means that it must be created with a return
type, a name, and a parameter list
The rules above give some restrictions on the parameter list
The name of an operator is always a conjunction of the keyword operator and
the operator symbol itself. Examples:
o operator+
o operator++
o operator<<
o operator==
So the format of an operator overload declaration is just like that of a function,
with the keyword operator as part of the name:
returnType operatorOperatorSymbol (parameterList);
Consider the arithmetic operators. These are already familiar notations from
algebra and earlier.
int x = 3, y = 6, z;
float a = 3.4, b = 2.1, c;
z = x + y;
5
c = a / b;
Now consider this notation. This should also be familiar from high school or
earlier:
1/2 + 1/3 // evaluates to 5/6
2/3 - 1/3 // evaluates to 1/3
Example
6
Overloading an operator as a member function
n3 = n1.operator+(n2);
But the whole point is to be able to use the more familiar notation, which still
works, and no dot-operator required:
Link to the Fraction class with the + operator as a member function . It’s a text
file.
7
With this function prototype, a sample call would be:
The + notation would certainly be more convenient. The operator version just
has a different name:
friend Fraction operator+(Fraction f1, Fraction f2);
n3 = operator+(n1, n2);
While this is legal, the advantage is being able to use the more
common infix notation:
Here's a full definition of the + operator for class Fraction. Note that this is
also a possible definition for the Add function:
Fraction operator+(Fraction f1, Fraction f2)
{
Fraction r; // declare a Fraction to hold the result
Once this operator overload is defined, then the following is legal. Note that
cascading also works (because the operation returns a Fraction). Now we have
the standard intuitive use of +
Fraction n1, n2, n3, n4, n5;
n5 = n1 + n2 + n3 + n4; // now it is legal!
Note: This function could also be written with const reference parameters
friend Fraction operator+(const Fraction& f1, const Fraction& f2);
8
Link to the Fraction class with operator+ added in (as a friend function)
As with other operators, the << and >> operators are defined for the basic types. If
you build your own class, don't expect << to automatically work with your new types
9
of objects! If you want it to work, you have to teach the computer how to do such
output. Consider the following:
Fraction f;
cout << f; // how would the machine know how to do this?
We have no reason to expect the second line to work! The insertion operator << is
only pre-defined for built-in types. The iostream.h library doesn't know about the
Fraction type.
The << operator is a binary operator (2 parameters, left side and right side). The first
parameter is always an ostream object (we've mostly used cout, so far). Because of
this, it cannot be defined as a member function (it would have to be a member of the
ostream class, which we cannot change). The << and >> operators should always be
defined as outside functions (usually friend functions). The second parameter is
whatever new type it is being overloaded to print:
friend ostream& operator << (ostream& s, Fraction f);
This declaration has all of the usual parts for defining a function. The name
is operator<< (the keyword operator and the operator symbol). The return type
is ostream&. The parameters are (ostream& s, Fraction f). When defining overloads
of << and >>, always pass the stream parameters by reference. A better way to write
this operator is:
friend ostream& operator << (ostream& s, const Fraction& f);
Notice that the first one passes the Fraction by value (and makes a copy). The second
passes by reference (avoiding the overhead of a copy). It is declared as a const
because the Fraction does not need to change if we are just doing output.
Notice that the Fraction parameter for >> is also a reference parameter. This is
because we are getting input into the object, so we need to work on the original, not a
copy.
10
Here is how the << operator might be defined for Fraction. Notice how similar it is to
the Show() function.
ostream& operator << (ostream& s, const Fraction& f)
{
s << f.numerator << '/' << f.denominator;
return s;
}
We can write:
cout << "Fraction f1 is " << f1 << '\n';
Click here to see the Fraction class with the << overload used instead of Show().
Now, what would the definition of the >> overload look like for Fraction? Try it!
You can check out sample prototypes for operator overloads here.
Here are some overly simplified iostream, ostream, and istream header files.
11
12