Function Overloading
In C, a function is uniquely identified by its name.
So code such as this
#include
void PrintGreeting ( void );
void PrintGreeting (char *message);
int main ( )
{
PrintGreeting( );
PrintGreeting ("Hello World\n");
return 0;
}
void PrintGreeting ( void )
{
printf ("Hi World\n");
}
void PrintGreeting (char *msg)
{
printf ("%s", msg);
}
results in compiler errors like this
CFunctions.c:5: conflicting types for `PrintGreeting'
CFunctions.c:4: previous declaration of `PrintGreeting'
CFunctions.c: In function `main':
CFunctions.c:9: too few arguments to function `PrintGreeting'
CFunctions.c: At top level:
CFunctions.c:16: conflicting types for `PrintGreeting'
CFunctions.c:5: previous declaration of `PrintGreeting'
CFunctions.c:21: conflicting types for `PrintGreeting'
CFunctions.c:16: previous declaration of `PrintGreeting'
This restriction requires you to create different names
for functions which perform virtually identical tasks.
In C++, functions are unqiuely identified by their name
AND their formal parameters (number and type). This combination of
information is called the function signature. This combination
allows you to have two or more functions with the same name if they have
different parameters.
This is known as function overloading.
(Note that a function's return type is NOT part of it's signature.)
When the code above is modified to be C++ code
#include
using namespace std;
void PrintGreeting ( );
void PrintGreeting (char *message);
int main ( )
{
PrintGreeting( );
PrintGreeting ("Hello World\n");
return 0;
}
void PrintGreeting ( )
{
cout << "Hi World\n";
}
void PrintGreeting (char *msg)
{
cout << msg;
}
It compiles without errors and creates an executable.
linuxserver1[140] g++ -ansi -Wall PrintGreeting.cpp
linuxserver1[141] a.out
Hi World
Hello World
Overloading Pitfalls and Function Resolution
As we learned in CMSC 201, when only one version of a function exists,
the compiler will use automatic type conversion (aka promotion) in order to call
that function when the argument type in the function call is not an exact match
for the formal parameter. For example, given the function
// mpg - returns miles per gallon
double mpg( double miles, double gallons)
{
return miles / gallons;
}
and the function call
cout << mpg( 45, 2 ) << endl;
the compiler will automatically convert (aka promote) the integers
45 and 2 to be of type double so that the function mpg( ) can be called.
This is a good thing and exactly what we want to happen. That's why
all the C language math functions (for example) have formal parameters of
type double.
With function overloading, we have to be careful not to give
the compiler too many choices. The interaction of overloading and
automatic type conversion can be confusing to you and the compiler.
Consider the (ill concieved) overloaded function f( ) below
void f( int n, double m);
void f( double n, int m);
and the function call
f (45, 2);
The compiler now has too many options. It can
- Promote the integer 2 to a double and call f(int n, double m)
- Promote the integer 45 to double and call f(double n, int m)
Given these ambiguous choices, the compiler will generate an
error message (as we saw with sqrt( ) and pow( )).
So, how do we solve this problem? How does the compiler decide
which overloaded function to call?.
The rules for resolving overloaded function calls are
- Exact Match -- if the number and types of the
arguments in the function call exactly match a function definition
(with no automatic promotion), then that is the function which is called.
- Match with Promotion -- if there is no exact match
but there is a match using automatic promotion, then that match is used
A compiler error is generated when
- Two exact matches are found
--- OR ---
- No exact matches are found, but two or more matches are found using
automatic type promotion
Either of these conditions lead to the error "call of overloaded 'function name'
is ambiguous".
So, how do we resolve the problem with the ill-concieved function f( ) above?
Last Modified: Monday, 28-Aug-2006 10:15:59 EDT