Function overloading is a C++ feature that can make your programs more readable. For example, suppose you write one square root function that operates on integers, another square root function for floating-point variables, and yet another for doubles. In C, you have to give them three different names, even though they all perform essentially the same task. But in C++, you can name them all square_root. By doing so, you “overload” the name square_root; that is, you give it more than one meaning.
When you declare multiple functions with the same name, the compiler distinguishes them by comparing the number and type of their parameters. The following example overloads the display_time function to accept either a tm structure or a time_t value.
// Overloaded functions for different data formats
#include <iostream.h>
#include <time.h>
void display_time( const struct tm *tim )
{
cout << "1. It is now " << asctime( tim );
}
void display_time( const time_t *tim )
{
cout << "2. It is now " << ctime( tim );
}
void main()
{
time_t tim = time( NULL );
struct tm *ltim = localtime( &tim );
display_time( ltim );
display_time( &tim );
}
The example gets the current date and time by calling the time and localtime functions. Then it calls its own overloaded display_time function once for each of the formats. The compiler uses the type of the argument to choose the appropriate function for each call.
Depending on what time it is, the previous example prints something like this:
1. It is now Wed Jan 31 12:05:20 1992
2. It is now Wed Jan 31 12:05:20 1992
The different functions described by an overloaded name can have different return types. This makes it possible to have a max function that compares two integers and returns an integer, and one that compares two floats and returns a float, and so on. However, the functions must also have different parameter lists. You cannot declare two functions that differ only in their return type. For example:
int search( char *key );
char *search( char *name ); // Error: has same parameter list
The compiler considers only the parameter lists when distinguishing functions with the same name.
You can also overload a name to describe functions that take different numbers of parameters but perform similar tasks. For example, consider the C run-time library functions for copying strings. The strcpy function copies a string from the source to the destination. The strncpy function copies a string, but stops copying when the source string terminates or after it copies a specified number of characters.
The following example replaces strcpy and strncpy with the single function name string_copy.
// An overloaded function
#include <iostream.h>
#include <string.h>
inline void string_copy( char *dest, const char *src )
{
strcpy( dest, src );
}
inline void string_copy( char *dest, const char *src, int len )
{
strncpy( dest, src, len );
}
static char stringa[20], stringb[20];
void main()
{
string_copy( stringa, "That" );
string_copy( stringb, "This is a string", 4 );
cout << stringb << " and " << stringa;
}
This program has two functions named string_copy, which are distinguished by their different parameter lists. The first function takes two pointers to characters. The second function takes two pointers and an integer. The C++ compiler tells the two functions apart by examining their different parameter lists.
Default arguments can make one function's parameter list look like another's. Consider what happens if you give the second string_copy function a default value for the len parameter, as follows:
string_copy( char *dest, const char *src, int len = 10 );
In this case, the following function call is ambiguous:
string_copy( stringa, "That" ); // Error
This function call matches both the string_copy that takes two parameters and the one that takes three parameters with a default argument supplied. The compiler cannot tell which function should be called, and gives an error.
You shouldn't overload a function name to describe completely unrelated functions. For example, consider the following pair:
void home(); // Move screen cursor to ( 0, 0 )
char *home( char *name ); // Look up person's home address
// and return it as a string
Since these functions perform totally different operations, they should have different names.