I tutor a few Computer Science Classes, so I decided that I might as well try to make a web page for various topics. This is the first one I worked on. It's about 5 pages long and written for a first semester C++ class. I hope you enjoy!

Function Overloading:

So what's this overloading thingie? And why's it good???

Hopefully, by now, you got the whole function thing down. We're going to throw a spin in on it. What is function overloading? It's having two functions of the same name.

Let's say you have a structure. Let's call it struct Circle. I'm also going to make an area() function to find the area. We might even define it like so:

struct Circle
{
 double radius;
};
double area(Circle); // Prototype

Circle TheCircle = {6.8}; // Global, for the sake of simplicity.

double area(Circle k)
{
   return k.radius * k.radius * 3.141;
}

Okay. Nothing new there, just like any other function or structure you've programmed. Well, I'm also going to need to keep track of some rectangles in my program. I'll add a rectangle structure in my program...

struct Rect
{
 double length;
 double height;
};

Rect TheRect = {4.5, 7.99};

I'm also going to need an area(Rect) function for the rectangles. But wait! We already have an area() function for the circle! The C solution? I can call the rectangle area function areaR(Rect), the circle are function areaC(Circle), and the triandle one areaT(Triangle), and so on (Yes! Must have triangles in my program too!). That's how old-style C did things. I might have 20 gazillion area functions, with 20 gazillion names, for 20 gazillion different shapes that all compute area slightly differently. Screw that! If I want to find the area of a pentagon I don't want to think about what the function name is, I just want to call area(Pentagon) or area(Whatever). The C Programming language doesn't allow the same function to take different arguments/parameters, so C++ has a better solution.

Why not give all the area functions the same name? It's easier to program if I can just call the function area and pass it a variable or structure and not worry about exactly what the area function's name is. I mean, it's OBVIOUS a rectangle object shouldn't use an area function that inputs circles if there's another area function that inputs rectangles. We'll let the compiler worry about what should go where. Some C++ code might look like this...

double area(Circle k); // prototypes
double area(Rect z);
// NOTE: they have the same function name! Amazing!

struct Circle
{
 double radius;
};

struct Rect
{
 double length;
 double height;
};

double area(Circle k)
{
   return k.radius * k.radius * 3.141;
}

double area(Rect z)
{
   return z.length * z.height;
}

Now, we can use the name "area" for both the Circle AND Rectangle area functions. Both area(Circle) and area(Rect) are now correct function calls, and we have the compiler figure out exactly which area function we want FOR us. This is not allowed in plain old C (you would need the area function names to be slightly different), but C++ is SMARTER than C!

Man, them plain C folks had it rough, eh?

When we have a function (ie area(Circle)), and we make a second version of it (ie area(Rect)), that's called (verb.) OVERLOADING the function. The function we did the OVERLOADING to (in this case, the area() function) is called the (adj.) OVERLOADED function.

Overloading Rules.

Yeah, Overloading does rule (as in Go Lakers! They rule!), but that's not the kind of rules we're talking about. These are the less interesting rules, the one's you must follow or else bad things will happen.

The first rule, is to not confuse the compiler. For example, if you're calling the area(Circle) function, don't make two prototypes that input only a single Circle. If you have two functions that match, which one is the compiler gonna pick?

// function call area(Circle) will go to this function.
double area(Circle);
// Or is it this function?
double area(Circle&); 
// Wait! area(Circle) could go here too!
double area(const Circle); 

Circle TheCircle = {8.8};
double AreaOfCircle = area(TheCircle); // Error!
// Which of the three area functions should you use?
// How sad... your compiler got confused...

Having all three of those functions at once will confuse your poor compiler. Which function should run? Your compiler may try to figure it out for a while before disappointedly giving up and returning an error message about how area(Circle) only needs to be defined once.

However, your compiler does have a few tricks up its sleeve. Imagine for a second that we have a function that takes in a double value, and returns the square root...

double sqrt(double); //prototype

However, if we call this function and pass in an integer, such as int y = sqrt(9);, your compiler will know that it should first turn the 9 into a double, and that the value returned, 3.0, should be turned into integer and not be double . Your compiler will do these things automagically, as in, it's magic! However, there are even more rules governing the use of this compiler magic...

When using overloaded functions, your compiler will attempt to match your function calls in the following matter.

Exact: An exact match. For instance, if we use the double sqrt(double); function above, then anytime we try to call the function using a double, the compiler will use the function that uses a double value for input. This should be pretty obvious. Why use the square root function that takes an integer when the square root function that takes doubles matches better? If there are multiple functions that make an exact match, the compiler complains and fails the compile since it cannot figure out which of the exact matching function to use.

double sqrt(double); //prototypes
double sqrt(&double);

... // misc code.

double y = 9.0;
double x = sqrt(y); // ERROR! 
// The compiler doesn't know which sqrt function to use.

// Yes, the compiler is pretty stupid. It gets confused easily.
// ...then again, even I wouldn't know which function to use...
// ...and NO. I'm NOT as stupid as the compiler, I swear.

Promotion: If there is no exact match, the compiler will try to use a function that will work just as well. For instance, if we had a function that took in long integers, but not plain integers, anytime we tried to use plain integers the compiler automatically promotes the integers to long integers:

long sqrt(long); // prototype
// Note: There is NO int sqrt(int) function...

... // misc code.

int x = 9;
long y = sqrt(x); // 'x' gets promoted to long.
// NOTE: 'x' is still an integer,
// but the '9' that got passed is type long.

If there are multiple ways for the compiler to promote a variable to use a function, there is an ambiguity error and the compile fails. Better to let you know than have the compiler pick a function at random.

long sqrt(long); // prototype
long long sqrt(long long); // ADDED! Another prototype
// Note: There is NO int sqrt(int) function...

... // misc code.

int x = 9;
long y = sqrt(x); // ERROR! 'x' is an int, 
// Should 'x' get promoted to long long, or just long?

Example Promotions: int to long, float to double, double to long double, etc...

Demotion: If there is no exact match, and there is no promotion match, then as a last resort, the compiler will try a demotion. There can be loss of accuracy here. For instance...

int sqrt(int); // prototype
// Note: There is NO double sqrt(double) function...

... // misc code.

double y = 9.9824573466573467;
double x = sqrt(y); // WARNING!
// Loss of accuracy! Forced to use the integer function.
// The above statement will give you a compiler WARNING,
// not an error. It will still compile.

// If you truely don't mind the loss of accuracy and
// want to get rid of the compile warnings, 
// you may typecast like so:

double x = sqrt( (int) y ); // No compile warnings.

Having the compiler use demotions is a GREAT way to introduce accuracy errors to your program! Especially if the compiler decides to cut off all digits after a decimal so that a floating point number can use an integer function. Example Demotions: int to float, float to int, long to int, long double to double, double to float, etc...

If there are multiple ways to demote a variable, you'll get compile errors. Doing any kind of demotions will also cause the compiler to give warnings (because you are losing accuracy), but it will not fail to compile. Also, if the compiler cannot find niether exact, promotion, nor demotion functions for your function call, the compile will fail.

Summary

  • You are allowed to have multiple functions of the same name as long as they input either different things or a different number of things.
  • The compiler will try to find exact matches for function calls. If it fails, it will then try to find promoted functions, then demoted functions. If it can't find any of those, the compiler will throw its non-existant hands in the air and give up.
  • If there are multiple functions that match a call (for example, no matching exact but two matching promoted functions), the compiler will complain about "ambiguity" and not compile.
  • If the compiler is forced to use a demoted function, it will give you a warning. I suggest you go back and either typecast if you truely don't care about your accuracy, or overload the function further so that there is an exact or promoted match.
  • Using demoted functions is a terrific way to get accuracy and rounding errors into your program. Get rid of those compile warnings, they should really really bug you, unless you're trying to make an inaccurate program, then by all means leave the warnings there.
  • I like pie. (Not the mathematical pi (π), though it's pretty damned cool too. But nothing's better than a nice warm cinnamon apple pie ready to eat.)
  • I lie about pie... There are things better than pie...
Please email me at kefabi@kefabi.com if anything is unclear, if there are factual/spelling errors, if you have any suggestions to improve this document, if you don't like my humor, or if you also like pie.
©2002 Garth Smith. This document may be distributed freely as long as there are no changes made to the document, credit is given to me (Garth Smith), and this copyright notice is left intact.

Log in or register to write something here or to contact authors.