CS 202 Fall 2013  >  Notes for Tuesday, October 1, 2013

CS 202 Fall 2013
Notes for Tuesday, October 1, 2013

Operator Overloading [14.5]

A Few Things Previously Covered

Overloading

Overloading a function means making two functions with the same name. In C++ we can do this as long as the functions have different parameter types.

[C++]

void foo(int a)
{ ... }

double foo(int a, int b)  // Okay
{ ... }

int foo(double x)         // Okay
{ ... }

int foo(int c)            // BAD!!!!
{ ... }                   // Same parameter types as 1st func

Parameter Passing

There are three ways to pass parameters in C++.

[C++]

X f(T by_value,
    T & by_reference,
    const T & by_reference_to_const);

We generally:

Return Values

We can also return by reference. But be careful! Do not return a reference to something that is going away (like most local variables).

[C++]

int & byref1()
{
    int x = 3;
    return x;  // BAD!!!
}

Some things are not going away, like reference parameters.

[C++]

int & byref2(int & x)
{
    return x;  // Okay
}

DRY

Remember the DRY principle: Don't Repeat Yourself.

We saw examples of this when we called a set-function (“mutator”) from a constructor. We already wrote the code to set the value. we used this code—without repeating it—in the constructor.

About Operators

Consider the expression “x * y”. The “*” is an operator. x and y are its operands.

An operator has precedence, associativity, and arity.

Precedence tells where the parentheses go when there are different kinds of operators. For example, “a + b * c” is the same as “a + (b * c)”, because * has higher precendence than +.

Associativiy tells where the parentheses go when the same kind of operator is used more than once. For example, “a / b / c” is the same as “(a / b) / c”, because the / operator is left-associative. But “a = b = c” is the same as “a = (b = c)”, because the = operator is right-associative.

Arity tells how many operands an operator has

The punchline: C++ allows us to write operator functions, which are called when an operator is encountered. We cannot create new operators, and we cannot change precedence, associativity, or arity. But we can overload existing operators for new types.

Writing Operator Functions

Operator functions can be member or global. I will look at writing them as global functions for now.

The name of an operator function is the word “operator” followed by the operator itself, for example, “operator>=”. Its parameters are the operands, and its return value is the result.

Here is the binary + operator for a class MyNum that I am writing.

[C++]

MyNum operator+(const MyNum & a, const MyNum & b)
{
    ...
}

I call this operator function using the “+” operator.

[C++]

int a, b, c;
a = b + c;  // Does NOT call my function

MyNum x, y, z;
x = y + z;  // Calls my function

Remember how we add global functions to a package: prototype in the header, definition in the source. A sample header file:

[C++]

// mynum.h
...
class MyNum {
    ...
};

MyNum operator+(const Mynum & a, const MyNum & b);
...

The corresponding source file:

[C++]

// mynum.cpp
...
#include "mynum.h"
...

MyNum operator+(const Mynum & a, const MyNum & b)
{
    ...
}

About return value methods:

Putting all these ideas together, here is a += operator.

[C++]

MyNum & operator+=(MyNum & a, const MyNum & b)
{
    ...
    return a;
}

When we do “a += b;”, we are modifying a, so we pass it by reference. We are not modifying the object b, so we pass it by reference-to-const. Since we modify an existing value, we return by reference.

We generally consider += to be more fundamental than +. The first operator contains the code to do addition. We can use the first operator to write the second.

[C++]

MyNum operator+(const Num & a, const MyNum & b)
{
    MyNum copy_a(a);
    copy_a += b;
    return copy_a;
}

The above is correct for just about any new kind of addition.

A more fundamental operator may need to access private class data. So it may need to be declared a friend.

[C++]

class MyNum {
    ...
    friend MyNum & operator+=(MyNum & a, const MyNum & b);
    ...
};

MyNum & operator+=(MyNum & a, const MyNum & b);

For today’s lab work, see the 10/1 Challenge.


CS 202 Fall 2013: Notes for Tuesday, October 1, 2013 / Updated: 1 Oct 2013 / Glenn G. Chappell