Wrox Press C++ Tutorial


Function Overloading

Suppose we have a function which generates the maximum value of an array of values of type double:

// Function to generate the maximum value in an 
// array of type double
double maxdouble(double array[], int len)
{
   double max = array[0];
   for(int i=1; i<len; i++)
      if(max<array[i])
         max = array[i];
   return max;
}

We now want to create a function which produces the maximum value from an array of type long, so we write another function very similar to the first, with this prototype:

long maxlong(long array[], int len);

We now have to be careful to choose the appropriate function name to match the particular task in hand. We may also need the same function for other types of argument. It seems a pity that we have to keep inventing new names. Ideally, we would want to use the function max() for whatever type, and have the appropriate version executed.

The mechanism which enables you to do this is called function overloading.

What is Function Overloading?

Function overloading allows you to use the same name in different functions and, in each instance, to have the compiler choose the correct version for the job. There has to be a clear method for the compiler to decide which function is to be called in any particular instance. The key to this is the parameter list. A series of functions with the same name, but differentiated by their parameter lists, is a set of overloaded functions. So, following on from our max() function example, we could have overloaded functions with the following prototypes:

int max(int array[], int len);         // Prototypes for
long max(long array[], int len);       // a set of overloaded
double max(double array[], int len);   // functions

Each of the functions that share a common name must have a different parameter list. Note that a different return type does not distinguish a function adequately. You can't add the function,

double max(long array[], int len);

to the above set as it would clash with this prototype,

long max(long array[], int len);

causing the compiler to complain and the program not to compile. This may seem slightly unreasonable, until you remember that you can write statements such as these:

long numbers[] = {1,2,3,3,6,7,11,50,40};
int len = sizeof numbers/sizeof number[0];
...
max(numbers, len);

If the return type were permitted as a distinguishing feature, the version of max() taking a long array as an argument and returning a double value would be allowed, along with the original three. In the instance of the code above, the compiler would be unable to decide whether to choose the version with a long return type or a double return type. You could however replace the long function with the double function in the set, as the parameter list for each function in the set would still be unique.

Each function in a set of overloaded functions is sometimes said to have a unique signature, which is determined by the parameter list.

Try It Out - Using Overloaded Functions

We can exercise the overloading capability with the function max() that we have already defined. Let's try an example that includes the three versions for int, long and double arrays.

// Ex5_06.cpp
// Using overloaded functions
#include <iostream>
using namespace std;

int max(int array[], int len);         // Prototypes for
long max(long array[], int len);       // a set of overloaded
double max(double array[], int len);   // functions

int main()
{
   int small[] = { 1,24,34,22};
   long medium[] = { 23,245,123,1,234,2345};
   double large[] = { 23.0,1.4,2.456,345.5,12.0,21.0};
   int lensmall = sizeof small/sizeof small[0];
   int lenmedium = sizeof medium/sizeof medium[0];
   int lenlarge = sizeof large/sizeof large[0];
   cout << endl << max(small, lensmall);
   cout << endl << max(medium, lenmedium);
   cout << endl << max(large, lenlarge);
   cout << endl;
   return 0;
}

// Maximum of ints
int max(int x[], int len)
{
   int max = x[0];
   for(int i=1; i<len; i++)
      if(max<x[i])
         max = x[i];
   return max;
}

// Maximum of longs
long max(long x[], int len)
{
   long max = x[0];
   for(int i=1; i<len; i++)
      if(max<x[i])
         max = x[i];
   return max;
}

// Maximum of doubles
double max(double x[], int len)
{
 double max = x[0];
   for(int i=1; i<len; i++)
      if(max<x[i])
         max = x[i];
   return max;
}

How It Works

We have three prototypes for the three overloaded versions of the function max(). In each of the three output statements, the appropriate version of the function max() is selected by the compiler based on the argument list types. The example works as expected and produces this output:

When to Overload Functions

Function overloading provides you with the means of ensuring that a function name describes the function being performed, and is not confused by extraneous information such as the type of data being processed. This is akin to what happens with basic operations in C++. To add two numbers you use the same operator, regardless of the types of the operands. Our overloaded function max() has the same name, regardless of the type of data being processed. This helps to make the code more readable and makes these functions easier to use.

The intent of function overloading is clear: to enable the same operation to be performed with different operands using a single function name. So, whenever you have a series of functions that do essentially the same thing, but with different types of arguments, you should overload them and use a common function name.


© 1998 Wrox Press