|
7: Function Overloading & Default Arguments
One of the important features in
any programming language is the convenient use of names.
When
you create an object (a variable), you give a name to a region of storage. A
function is a name for an action. By making up names to describe the system at
hand, you create a program that is easier for people to understand and change.
It’s a lot like writing prose – the goal is to communicate with your
readers.
A problem arises when mapping the concept
of nuance in human language onto a programming language.
Often, the same word expresses a number of different meanings, depending on
context. That is, a single word has multiple meanings – it’s
overloaded. This is very useful, especially when it comes to trivial
differences. You say “wash the shirt, wash the car.” It would be
silly to be forced to say, “shirt_wash the shirt, car_wash the car”
just so the listener doesn’t have to make any distinction about the action
performed. Human languages have built-in redundancy, so even if you miss a few
words, you can still determine the meaning. We don’t need unique
identifiers – we can deduce meaning from
context.
Most programming languages, however,
require that you have a unique
identifier for each function. If you have three different types of data that you
want to print: int, char, and float, you generally have to
create three different function names, for example, print_int( ),
print_char( ), and print_float( ). This loads extra work
on you as you write the program, and on readers as they try to understand
it.
In C++, another factor forces the
overloading of function names: the constructor. Because
the constructor’s name is predetermined by the name of the class, it would
seem that there can be only one constructor. But what if you want to create an
object in more than one way? For example, suppose you build a class that can
initialize itself in a standard way and also by reading information from a file.
You need two constructors, one that takes no arguments (the default constructor)
and one that takes a string as an argument, which is the name of the file
to initialize the object. Both are constructors, so they must have the same
name: the name of the class. Thus, function overloading is essential to allow
the same function name – the constructor in this case – to be used
with different argument types.
Although function overloading is a must
for constructors, it’s a general convenience and can be used with any
function, not just class member functions. In addition, function overloading
means that if you have two libraries that contain functions of the same name,
they won’t conflict as long as the argument lists are different.
We’ll look at all these factors in detail throughout this
chapter.
The theme of this chapter is convenient
use of function names. Function overloading allows you to use the same name for
different functions, but there’s a second way to make calling a function
more convenient. What if you’d like to call the same function in different
ways? When functions have long argument lists, it can become tedious to write
(and confusing to read) the function calls when most of the arguments are the
same for all the calls. A commonly used feature in C++ is called default
arguments. A default
argument is one the compiler inserts if it isn’t specified in the function
call. Thus, the calls f(“hello”), f(“hi”,
1), and f(“howdy”, 2, ‘c’) can all be calls
to the same function. They could also be calls to three overloaded functions,
but when the argument lists are this similar, you’ll usually want similar
behavior, which calls for a single function.
Function overloading and default
arguments really aren’t very complicated. By the time you reach the end of
this chapter, you’ll understand when to use them and the underlying
mechanisms that implement them during compiling and
linking.
|
|