Most of this lecture involves function overloading. This concept/feature may not seem too important right now, but as we progress in our understanding of programming and in our knowledge of C++, the importance of overloading will become more apparent. We're talking about it now because it should help you understand the role of types even better, and why we say that understanding types is one of the most important things you can get out of this class!
It's also of note that C does not allow overloading of functions, and this is another one of those handy C++ things. Even if you find yourself only using C in the future, this topic is helpful in deepening your understanding of types, and understanding the different constraints under which each programming language uniquely has.
void
rep(char,int);, and with the following definition:
void rep(char c, int k) {
for( int i = 0; i < k; i++ )
cout << c;
}
| Code | Resulting Output | Explanation |
|
| Clear from the function definition. |
|
| rep expects a char as its first
argument, but the first argument in the function call,
y, is an int. Thus,
y gets converted to a char to
match the prototype, and the char
interpretation of 42 (as we see from the ASCII
table) is '*'.
|
|
| rep expects a char as its first
argument, but the first argument in the function call,
z, is a double. Thus,
z gets converted to a char to
match the prototype, and the char
interpretation of 42.553 is ASCII value 42, which is
'*'.
|
rep, but with different types of arguments?
For example, what if I have the following program
| Prototypes | Definitions | main |
|
|
|
X's to be printed, and
Alternative Two causes
555555555555
... to be printed. Why the difference? Which function gets used?
Well, in Alternative One we
used an object of type char as the first argument, so
it used the version of rep with an object of type
char as a first argument.
In Alternative Two we
used an object of type int as the first argument, so
it used the version of rep with an object of type
int as a first argument. This is called
overloading of function names. The idea is, that the
name of a function isn't just rep,
the name of the function is really rep(int,int)
or rep(char,int). So:
Overloading of a function name occurs when two or more definitions are given for functions with the same name, but different number or types of arguments.
Note: the return type of a function is not
considered in function overloading. Thus, it is illegal to have
two functions whose prototype differs only in the return type.
For example: double f(int); and
char f(int); cannot coexist!
| Definition 1 | Definition 2 | Discussion |
|
|
No conflict here, because I can look at the number of arguments and decide which function to call |
|
|
No mystery here! If you see a call like
mystery('X',13) you'd know that
mystery(char,int) (i.e. the second
definition) would be called. You just figure out which
prototype matches. |
| Definitions | Function Call | Discussion |
|
|
Error! This function call is ambiguous! The
compiler has no way of knowing:
|
rep(42.23,10); to
rep(char(42.23),10);, thus removing any
ambiguity.
line(int k) that prints a line of k
asterisks. And just to be on the safe side, let's make sure our
function still works properly when negative k's are
passed to it. "Works properly" in this case means, does nothing!
void line(int k) {
// Takes care of bad arguments!
if( k < 0 )
return;
// Takes care of everything else!
for( int i = 0; i < k; i++ )
cout << '*';
cout << endl;
}
If you call this function with an argument like 35, you get:
***********************************
Now, suppose I want to modify this so that it prints a second line
below of length k-1, so that calling this function
with an argument like 35 would give me
***********************************
**********************************
Well, I might decide to try the following idea. Since
line already does all the work of printing out a
line for me, why don't I just add a line(k-1) at the
end of my function definition? In other words, how aobut:
void line(int k) {
// Takes care of bad arguments!
if( k < 0 )
return;
// Takes care of everything else!
for( int i = 0; i < k; i++ )
cout << '*';
cout << endl;
// Print next line?
line(k-1);
}
Well, if I compile and run this with something like
line(10), here's what I get:
**********
*********
********
*******
******
*****
****
***
**
*
So what happened? A function that "calls itself" as this one does is
called recursive. Step through this
program and see what's really going on here!