CSC262 Jan18

slide version

single file version

Contents

  1. Function Overloading
  2. Example - Pair.h
  3. Example - Pair.cpp
  4. Example - testPair.cpp
  5. Operator Overloading
  6. Overloading + for the Pair Class
  7. Operators as Functions
  8. Operator Function Names
  9. Overloading + for the Pair Class
  10. Operator + as a Member of Pair
  11. Revised Pair.h
  12. Revised Pair.cpp
  13. Calling operator+
  14. The testPair Program Revised
  15. Problem
  16. Overloading Operators as Non-member Functions
  17. The Non-Member operator+
  18. A Correct Non-Member operator+
  19. Non-member operator+ - where?
  20. Friend Functions
  21. Declaring operator+ as a Friend

Function Overloading[1] [top]

Function overloading refers to defining two different functions in the same scope that have the same name.

These functions must different in their parameter lists - either in the number of parameters or in the parameter types.

Example - Pair.h[2] [top]


class Pair
{
  int x, y;
public:
  Pair();
  Pair(int xval, int yval);

  int getX();
  int getY();
  string toString();
  Pair add(const Pair& other);
  Pair add(int d);
  
};

Example - Pair.cpp[3] [top]


#include "Pair.h"

Pair::Pair() {
  x = 0;
  y = 0;
}

Pair::Pair(int xval, int yval)
{
  x = xval;
  y = yval;
}

Pair Pair::add(const Pair& other)
{
  int xval = x + other.x;
  int yval = y + othery.y;

  return Pair(xval, yval);
}

Pair Pair::add(int d)
{
  int xval = x + d;
  int yval = y + d;

  return Pair(xval, yval);
}
...

Example - testPair.cpp[4] [top]


#include "Pair.h"

int main()
{
  Pair p1(2,3);
  Pair p2(5,5);

  Pair p3, p4;

  p3 = p1.add(p2);
  p4 = p1.add(1);

  cout << "Expecting p3 = (7,8)" << endl;
  cout << "p3 = " << p3.toString() << endl;

  cout << "Expecting p4 = (3,4)" << endl;
  cout << p4.toString() << endl;

  return 0;
}

Operator Overloading[5] [top]

In C++, it is possible to overload operators in addition to overloading functions.

For example, we can overload the + operator with some restrictions.

An example restriction is that you can't overload the meaning of operators for basic types (non-class types) like int, float, double, char, etc.

So you can't make 4 + 2 be 42 or any other arbitrary value other than 6.

You can overload operators if one or more of the operands is of class type.

Overloading + for the Pair Class[6] [top]

We would like to write

  Pair p1(2,3);
  Pair p2(5,5);

  Pair p3, p4;

  p3 = p1 + p2;  // instead of p1.add(p2)
  p4 = p1 + 1;   // instead of p1.add(1)

    

Note that the values assigned to p3 and p4 don't change, we are just able to write the operator + instead of the member function add. But the implementation will be the same!

How do you declare and implement an new meaning for an operator. That is, how do you overload an operator?

Operators as Functions[7] [top]

We already know how to overload a function.

The trick to overloading an operator is that in C++, each operator has a corresponding function name.

To overload the operator, just overload its function!

But what is the name of the function that corresponds to the operator +?

Operator Function Names[8] [top]

Operator Operator
Function Name
+ operator+
- operator-
* operator*
/ operator/

And so on...

Almost all operators can be overloaded. The member selection operator "." is one exception.

However, ->, <<, and >> are also operators and they can be overloaded.

Overloading + for the Pair Class[9] [top]

We want to define + to mean the same thing as the add member function of Pair.

So the new definition of + for Pair is naturally defined as a member of the Pair class.

Operator + as a Member of Pair [10] [top]

Recall we want to use + this way:

Pair p1(2,3);
Pair p2(5,5);
Pair p;

p = p1 + p2;      
    

But to implement this we need to write a member function named operator+

Revised Pair.h[11] [top]

Here is the revised Pair.h


class Pair
{
  int x, y;
public:
  Pair();
  Pair(int xval, int yval);

  int getX();
  int getY();
  string toString();
  Pair add(const Pair& other);
  Pair add(int d);

  Pair operator+(const Pair& other);
  Pair operator+(int d);
  
};

Note the operator+ functions are declared (and implemented) with the same parameters as the corresponding add member functions.

Revised Pair.cpp[12] [top]

For example, the Pair.cpp file would contain the same member function implementations, but with 2 more for the operator+ members:


Pair Pair::add(const Pair& other)
{
  int xval = x + other.x;
  int yval = y + othery.y;

  return Pair(xval, yval);
}

Pair Pair::operator+(const Pair& other)
{
  int xval = x + other.x;
  int yval = y + othery.y;

  return Pair(xval, yval);
}

Calling operator+[13] [top]

The compiler (but not programmers) look at

Pair p1(2,3);
Pair p2(5,5);
Pair p3, p4;

p3 = p1.add(p2);
p4 = p1 + p2;
    

like this

Pair p1(2,3);
Pair p2(5,5);
Pair p3, p4;

p3 = p1.add(p2);
p4 = p1.operator+(p2);
    

The testPair Program Revised[14] [top]


#include "Pair.h"

int main()
{
  Pair p1(2,3);
  Pair p2(5,5);

  Pair p3, p4;

  p3 = p1 + p2; // instead of p1.add(p2);
  p4 = p1 + 1;  // instead of p1.add(1);

  cout << "Expecting p3 = (7,8)" << endl;
  cout << "p3 = " << p3.toString() << endl;

  cout << "Expecting p4 = (3,4)" << endl;
  cout << p4.toString() << endl;

  return 0;
}

Problem[15] [top]

For numbers, of course

a + 1 is the same as 1 + a
    

So we might want to write

  Pair p1(2,3);
  Pair p2(5,5);

  Pair p;

  p = 1 + p1; // PROBLEM

The expression

      1 + p1      
    

cannot mean

      1.operator+(p1)      
    

since 1 is not a Pair.

Overloading Operators as Non-member Functions[16] [top]

We can still make this work by providing one more function to overload operator+.

But it can't be a member function of the Pair class, since the left operand is an ordinary integer, not a Pair.

A non-member operator+ function can/must be called without using the "." member selection.

But this operator will still need 2 operands - the integer and the Pair.

The Non-Member operator+[17] [top]

Here is the member operator+ that works for

For

Pair p1(2,3);
Pair p;

p = p1 + 1;      
    

Here is the member operator+ that works


Pair Pair::operator+(d)
{
  int xval = x + d;
  int yval = y + d;

  return Pair(xval, yval);
}

The non-member operator+ that would work for

Pair p1(2,3);
Pair p;

p = 1 + p;      
    

might be expected to be


Pair operator+(int d, const Pair& other)
{
  int xval = d + other.x;
  int yval = d + other.y;

  return Pair(xval, yval);
}

But other.x is illegal!

Since this operator+ is not a member function it can't access the private members of Pair!

A Correct Non-Member operator+[18] [top]

We can easily fix this by using the public getX and getY


Pair operator+(int d, const Pair& other)
{
  int xval = d + other.getX();
  int yval = d + other.getY();

  return Pair(xval, yval);
}

Non-member operator+ - where?[19] [top]

This non-member operator+ logically belongs with the Pair class. A class is a unit that keeps the related member functions of the class declared in one place (the Pair.h file) and defined in one place (the Pair.cpp file).

But where can we put the non-member operator+

We could declare it in the Pair.h file, but outside the class declaration:


class Pair
{
  int x, y;
public:
  Pair();
  Pair(int xval, int yval);

  int getX();
  int getY();
  string toString();
  Pair add(const Pair& other);
  Pair add(int d);

  Pair operator+(const Pair& other);
  Pair operator+(int d);
  
};
Pair operator+(int d, const Pair& p);

and write the implementation in the Pair.cpp file

Friend Functions[20] [top]

C++ provides an alternative: friend functions of a class.

A friend function is a non-member function that is declared inside a class with the friend qualifier.

The friend qualifier tells the compiler this is not a member function of Pair, but if one of its parameters is of type Pair, then the friend function can access the private members of that Pair.

Declaring operator+ as a Friend[21] [top]


class Pair
{
  int x, y;
public:
  Pair();
  Pair(int xval, int yval);

  int getX();
  int getY();
  string toString();
  Pair add(const Pair& other);
  Pair add(int d);

  Pair operator+(const Pair& other);
  Pair operator+(int d);
friend Pair operator+(int d, const Pair& p);
  
};

In the Pair.cpp file, the friend qualifier is not repeated.


Pair Pair::operator+(const Pair& other)
{
  int xval = x + other.x;
  int yval = y + othery.y;

  return Pair(xval, yval);
}

// Don't repeat friend in Pair.cpp
Pair operator+(int d, const Pair& other)
{
  int xval = d + other.x;
  int yval = d + other.y;

  return Pair(xval, yval);
}