Generic
functions allow you to specify different arguments list for an abstract function
type. This allows the programmer more flexibility in specifying the argument
list for a function.
To
give an idea of how these functions are used here is an example:
double overloaded sqrt(double);
int overloaded sqrt(int);
This
declares two different functions that will get an automatic name furnished by
the compiler. Those functions will be selected at the call site according to
their arguments list: if the argument list is a double, the first function will
be called and the type of the resulting expression is a double. If an integer is
given, the second function will be selected and the resulting type is integer.
The
exact syntax is:
1)
Short form:
<return type> overloaded identifier (
argument-list )
Example:
double overloaded sqrt(double);
The
compiler will supply here automatically a name for this function. The name will
be constructed from the overloaded identifier and the argument list.
Long
form:
<return type> overloaded identifier .
identifier ( argument-list )
Example:
double overloaded sqrt.DblSqrt(double);
int overloaded sqrt.IntSqrt(int);
The
long form allows the programmer to override the automatic name of the function
and furnish its own. This is important since it allows for easy interfacing of
the software that uses this extension with other software.
This
extension doesn’t introduce a new keyword. You can still define
int overloaded = 0;
or
int overloaded(int a);
or even
typedef int *overloaded;
overloaded foo(int a);
and
this will compile as you would expect. In the last example the typedef
definition is used, since overloaded functions can’t have an implicit
“int” result: they must be given a full prototype.
If
you need (for whatever reason) to force the compiler to choose one of the
overloaded functions, you should use the long notation and just call the
function in question:
double overloaded
sqrt.DblSqrt(double);
int overloaded sqrt.IntSqrt(int);
You
can force calling the first function just with:
double s = DblSqrt(4.9);
The
DblSqrt function will be visible in the current scope after the “overloaded”
declaration is seen.
·
You can add any number of overloaded arguments
lists to an identifier, but once the first call to such a function is generated,
it is impossible to add a new definition.
For
instance :
double overloaded sqrt(double);
int overloaded sqrt(int);
int foo(void)
{
double a = sqrt(2.3);
}
double
overloaded sqrt(complex) ;
This is an error. All overloaded function definitions must be present when the first call is generated.
· You must supply the « overloaded » marker at the declaration and at the definition of the function. For instance, it is an error when you write :
double
overloaded sqrt(double) ;
double
sqrt(double) // error : redefinition of sqrt.
{
…
}
This
extension is very useful for constructors. For instance consider:
typedef struct _Person {
char *Name;
int Age;
} Person;
We
can define several overloaded constructors for this data structure:
Person * overloaded newPerson(void)
{
return (Person *)malloc(sizeof(Person));
}
Person *newPerson(char *name)
{
Person *result = malloc(sizeof(Person));
result->Name = name;
return result;
}
Person *newPerson(char *Name,int
age)
{
Person *result = (Person *)malloc(sizeof(Person));
result->Name = name;
result->Age = age;
return result;
}
etc.