Professional Documents
Culture Documents
Parameter Functions II
Functions must be bothering you by now. Many chapters ago you were
introduced to simple functions. Life was good back then. There was minimal
headaches about parameters, and modularity was the main concern. Now you are
getting bombarded by functions and the end does not seem to be in sight yet.
The last chapter introduced user-defined functions that used parameters. You
used both void and return functions. The name of the parameters in those
functions were called value parameters. A value is passed to a function. The
function makes a copy of the passed value, and processes information according
to the program statements in the function.
Now there is still more function business. In this chapter we will talk about
variable or reference parameters. This type of parameter is very different from
the earlier value type. It appears that this parameter has the ability to pass
information back to the calling program segment.
Take all this parameter business seriously. You need a very thorough, solid,
understanding of parameters. It will be the foundation of everything that follows
in future chapters. Whether you continue computer science in high school or
whether you continue in college or the business world, computer science will
expect a thorough knowledge of parameters.
One word of warning before you plunge into this chapter. You need to be on
fairly solid ground with void functions and return functions. If you have casually
glanced through the previous chapter or if you are unsure, even after serious
studying, go back. Adding the information in this chapter on top of existing
function-confusion will not be real productive. Study the previous chapter some
more, get extra help, but whatever you do, learn the previous material first.
Simple void functions can only pass information with global variables. That is a
serious nono. Ugly, yukky, side effects can creep into your programs with global
variable information passing. You did use that approach for a while for the sake
of going through a gentle introduction to program modularity. That stage has now
passed and you are entering the proper world of programming development.
Void functions with value parameters pass information in one direction. The
program segment that calls the function sends information to the function. The
void function is on the receiving end of the parameter passing business. We also
have return functions that have the ability to return information from the function.
These functions receive information - usually with value parameters - digest the
information and return some value. We could call these return functions, two-
way information functions.
There is yet another information passing approach. You can also use void
functions that are two-way information functions. The purpose of this section is
to investigate how it is possible - and why it is desirable - to use void functions
for any two-way information schemes.
Take a quick look at two return functions that were shown in the previous chapter.
Program PROG1401.CPP and PROG1402.CPP use functions that return the
next integer and the upper-case of a lower-case letter. These programs are
repeated for comparison reasons.
// PROG1401.CPP
// This program uses a return function to get the next
integer.
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int Number;
cout << "ENTER AN INTEGER ===>> ";
PROG1401.CPP OUTPUT
NEXT INTEGER IS 20
// PROG1402.CPP
// This program uses a return function to change a
lower-case
// letter to an upper-case letter.
#include <iostream.h>
#include <conio.h>
void main()
{
char Letter;
clrscr();
cout << "ENTER A LOWER CASE LETTER ===>> ";
cin >> Letter;
cout << endl;
cout << "UPPER CASE LETTER (IF POSSIBLE) IS "
<< UpCase(Letter);
cout << endl;
getch();
}
PROG1402.CPP OUTPUT
// PROG1403.CPP
// This program uses a void function to get the next
integer.
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int Number;
cout << "ENTER AN INTEGER ===>> ";
cin >> Number;
cout << endl;
NextInt(Number);
cout << "NEXT INTEGER IS " << Number << endl;
getch();
}
NEXT INTEGER IS 20
Void function NextInt is different from the return function NextInt because of
the difference between void and return functions. That is not new. Both the
function syntax and the function calling approach is different between void and
return functions. These differences can be reviewed in the last chapter. The
difference you should have observed is an odd looking ampersand (&) in the
function heading of NextInt.
The output of the program indicates that it does provide the next integer to the
main function. Try the program yourself, you will find that it works correctly and
apparently behaves in the same manner as the earlier program with the return
function.
Now look at program PROG1404.CPP and see if you can detect any type of
pattern. This program alters a lower-case letter to an upper-case letter. You can
trust the provided output, but better yet, type the program in yourself and test
yourself to see that the output matches your expectations.
// PROG1404.CPP
// This program uses a void function to change a lower-
case
// letter to an upper-case letter.
#include <iostream.h>
#include <conio.h>
PROG1404.CPP OUTPUT
You are entirely unimpressed. Right now it seems that void functions with the
assistance of a weirdly placed (&) manage to accomplish the same task as the
return function already did in the last chapter. Furthermore, you were much more
impressed with the return function’s approach. Each return function performed its
required process and at the conclusion of the function, the clever return statement
passed the appropriate value back to the calling program segment.
Now computer scientists as a rule are a logical bunch of people. The inclusion
and creation of some feature is normally for the purpose of accomplishing
something that cannot be done some other way. At least the required task cannot
be done as efficiently without the newly included feature.
You see, return functions have one very important limitation: return functions
only return one value. The examples that were used returned the next integer and
the upper-case letter. Consider all the common math functions, like square root,
absolute value and rounding off. All such functions only return a single value. In
each one of those situations you should use a return function. But there are other
situations and a good example is function Swap. This functions requires that two
parameters exchange their values. In other words, two values need to be returned
to the calling program segment. In this case the return function politely bows its
head and allows some other function to do the job.
Program PROG1405.CPP demonstrates how to exchange values with a Swap
void function that uses two variable parameters.
// PROG1405.CPP
// This program returns two altered parameters.
// It demonstrates a swap function.
#include <iostream.h>
#include <conio.h>
PROG1405.CPP OUTPUT
A = 5
B = 7
A = 7
B = 5
The Swap function does not show any special magic. The same & business
shown with NextInt and UpCase is now done with Swap. The & is used twice
because we are using two variable parameters, but logically the concept is the
same. This type of function is precisely why void functions with two-way
parameters exist. Try swapping with a return function. You will need some
serious imagination to accomplish that trick.
By the way, note how program PROG1406.CPP cleverly uses the Swap
function that we introduced in the previous program. In one program we use two
void functions that use two-way parameter passing. Pretty impressive stuff. The
actual code in function Sort can be altered. There are a variety of techniques to
sort data. The sorting approach demonstrated works, and the main point of the
function is to show an example of using two-way parameter passing.
// PROG1406.CPP
// This program sorts three numbers from smallest to
largest.
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int N1,N2,N3;
cout << "Enter three integers ===>> ";
cin >> N1 >> N2 >> N3;
Display(N1,N2,N3);
Sort(N1,N2,N3);
Display(N1,N2,N3);
getch();
}
PROG1406.CPP OUTPUT
3 1 2
1 2 3
This chapter introduced the new idea of using void functions with two-way
parameters. Information is passed from the function call to the function and after
some process - such as sorting - altered information is passed back to the program
segment of the function call. All the program examples have used functions that
either used value (one-way) parameters exclusively or used only variable (two-
way) parameters exclusively. It is also possible to mix both types of parameters
in one function. In this section we will look at a simple payroll program and
observe what types of parameters will be used in each function. Along the way,
you will note that it is very normal to have functions that use a combination of
value and variable parameters.
The payroll program will also demonstrate how to pass information in a program.
You will note that all information that is passed between the functions is passed
by parameters. Passing information with global variables was a temporary stage
in your computer science development. As a matter of fact, it will be wise not to
mention this stage to other computer science people. Many folks in the computer
science community will be shocked that you were exposed to evil, global,
information passing.
The first step is to consider the main function of the payroll program. At this
stage you decide what information is required to and from each function called in
the main program function. At every stage, ask the question if the information
will change or if the information is now fixed and will no longer be altered. That
answer will determine if a parameter becomes a value or variable parameter. Do
not turn the page too quickly. See if you can pick the proper parameters yourself.
// PROG1407.CPP
// This program computes a simple payroll.
// It demonstrates value, reference and mixed
parameters.
void main()
{
int HoursWorked; // hours worked per week
double HourlyRate; // payrate per hour
double GrossPay; // pay before deductions
double Deductions; // tax deductions
EnterData(HoursWorked,HourlyRate);
CompGross(HoursWorked,HourlyRate,GrossPay);
CompDeduct(GrossPay,Deductions);
CompNet(GrossPay,Deductions,NetPay);
DisplayData(HoursWorked,HourlyRate,GrossPay,Deductions,
NetPay);
}
The next level of our payroll program identifies the value and variable
parameters. This is a good example of the virtue of using prototypes. Placing the
prototypes ahead of the main function allows you to view the communication
between the main function and the major functions in the program. This makes it
easier to decide on the nature of each parameter.
// PROG1407.CPP
// This program computes a simple payroll..
// It demonstrates value, reference and mixed parameters.
#include <iostream.h>
#include <conio.h>
#include <iomanip.h>
void main()
{
int HoursWorked; // hours worked per week
double HourlyRate; // payrate per hour
double GrossPay; // pay before deductions
double Deductions; // tax deductions
double NetPay; // total take-home pay
EnterData(HoursWorked,HourlyRate);
CompGross(HoursWorked,HourlyRate,GrossPay);
CompDeduct(GrossPay,Deductions);
CompNet(GrossPay,Deductions,NetPay);
DisplayData(HoursWorked,HourlyRate,GrossPay,Deductions,NetPay);
}
The next function call needs to compute the gross pay of the employee. This is
done with function CompGross. In this function HW and HR will be used to
compute the gross pay, GP. This means that HW and HR will not change and are
value parameters. GP does change and must be a variable parameter.
We now follow the same logic with function CompDeduct. This function takes
the gross pay, GP, and computes deductions, DD, based on total earnings. GP
now does change and is a value parameter. Deductions, DD, does change and
becomes a variable parameter.
You have figured it out, right? In function CompNet, the only parameter that
changes is the net pay, NP. Parameters GP and DD are used to compute NP, and
will not change.
Check out the complete payroll program now. In particular, trace the information
as it is passed between the different program modules. Stick with this program
until it is clear to you why parameters are value or why they are variable.
// PROG1407.CPP
// This program computes a simple payroll.
// It demonstrates value, reference and mixed
parameters.
#include <iostream.h>
#include <conio.h>
#include <iomanip.h>
void main()
{
int HoursWorked; // hours worked per week
double HourlyRate; // payrate per hour
double GrossPay; // pay before deductions
double Deductions; // tax deductions
double NetPay; // total take-home pay
DisplayData(HoursWorked,HourlyRate,GrossPay,Deductions,
NetPay);
}
void DisplayData(int HW, double HR, double GP, double DD, double NP)
PROGRAM PROG1407.CPP
Hours Worked: 17
Hourly Rate: 6.85
Gross Pay: 116.45
Deductions: 26.38
Net Pay: 90.07
We are not finished with this function business, but before we move on you need
to have a good, solid grasp of the vocabulary used with parameters. You will be
better prepared for future computer science courses, and my job will be simpler in
future chapters when I can assume a strong foundation in parameter terminology.
The complexity with parameter vocabulary is the result of two facts. First, there
are a variety of names for the exact same concepts, and you need to be sure that
Do not get flustered by this. Look at high school students and see how many
names are given to the same person. First, let's name according to class. Fine,
you are Sophomore, Junior or Senior. Second, let's name according to grades.
This makes you an A, B, or C student. (computer science students do not fail)
Third, let's name according to activities like band, tennis team, Mu Alpha Theta,
JETS, student council, etc. And, let's not forget to name according to first name
like Joe, Sue, Kathy, Tom, Mary, etc. The point here is that placing a label on a
person depends on the category of the label.
Parameters do a poor job hiding. You will find them in only two locations. A
parameter is either in a function call or a function heading. There is no other
place that a parameter can visit. We wish to label these two locations.
Parameters in a function call are actual parameters and parameters in a function
heading are formal parameters.
// PROG1405.CPP
// This program returns two altered parameters.
// It demonstrates a swap function.
#include <iostream.h>
#include <conio.h>
void main()
{
int N1 = 5, N2 = 7;
clrscr();
Display(N1,N2);
Swap(N1,N2);
Display(N1,N2);
getch();
}
In this program, N1 and N2 are actual parameters. Both parameters are used in
function calls Display and Swap. A and B are formal parameters, located in the
functions headings. Technically, the formal parameters in Display and Swap are
in a totally different scope. It is customary to give them the same name, because
formal parameters A and B work with the same actual parameters N1 and N2.
This chapter introduced the fancy parameters that can pass information in both
direction, which are casually called two-way parameters. The more precise
terminology is variable parameter, or even more precisely preferred, reference
parameter, because the function is invoked call-by-reference. The next section
will explain why the name reference parameter is very appropriate.
// PROG1405.CPP
// This program returns two altered parameters.
// It demonstrates a swap function.
#include <iostream.h>
#include <conio.h>
void main()
{
int N1 = 5, N2 = 7;
clrscr();
Display(N1,N2);
Swap(N1,N2);
Display(N1,N2);
getch();
}
Perhaps I can also explain why a formal parameter is called formal. In this case,
formal has nothing to do with formal in the tuxedo sense. Think of it as the form
of the parameter. Consider this: can you look at a function call and always
determine by those actual parameters if information is passed by value or by
reference? No, that is not possible in every case. If the actual parameter is a
constant, you can conclude that it must be a value parameter, but otherwise you
do not have a clue.
The parameters in a function heading are another story. Here the parameters
appear with or without the (&) operator. Without (&) means value parameter
and with (&) means variable parameter. In other words, you can determine the
form of the parameter in the function heading. Hence the term formal parameter.
First, you need to take a closer look at memory locations. Since the early chapters
you have been told that data is stored in memory. Different data occupies
different amounts of memory, but somewhere the data is stored. With C++ it is
possible to find the exact memory location where a variable stores its information.
It can be done with the reference operator. In this chapter the & has been used to
indicate that a parameter is a variable or reference parameter. You are about to
learn a more technical side to the humble reference (&) operator. We can stick an
& in front of any variable and display the memory of that variable.
// PROG1408.CPP
// This program demonstrates memory locations of
variables.
#include <iostream.h>
#include <conio.h>
void main()
{
int IntVar1 = 1000;
int IntVar2 = 2000;
float FloatVar1 = 3.14159;
float FloatVar2 = 1.23456;
clrscr();
cout << "IntVar1 is " << IntVar1 << endl;
cout << "IntVar2 is " << IntVar2 << endl;
cout << "FloatVar1 is " << FloatVar1 << endl;
cout << "FloatVar2 is " << FloatVar2 << endl;
cout << endl;
PROG1408.CPP OUTPUT
IntVar1 is 1000
IntVar2 is 2000
FloatVar1 is 3.14159
FloatVar2 is 1.23456
This first memory example program demonstrates two things. First, you do notice
the hexadecimal (base 16) memory addresses. It does prove that the reference
(&) operator can provide us with memory addresses.
Something else can be seen. C++ grabs adjacent memory locations, whenever
possible. Observe the memory locations. The output helps to show that float
occupies 4 bytes in memory and int reserves 2 bytes.
The numbering sequence may seem odd at first. Do keep in mind that memory is
allocated from a higher memory address down to lower addresses. Also keep in
mind that in base 16 the (base 10) values 10, 11, 12, 13, 14, 15 are represented
with a, b, c, d, e, and f. Frankly, for the purpose of this chapter, it matters little if
you know base 16 from mushroom pizza. The program examples in this section
display memory locations. Some memory addresses are the same number,
indicating that they occupy the same location. Other memory addresses have
different numbers, indicating that they are different locations.
The most important concept to understand in this section is how it is possible for
more than one identifier to store information in the same memory location. A
significant consequence of two variables occupying the same memory location is
In function CheckMem there are corresponding Ref2 and Val2 parameters that
represent the local, formal parameters of the function. The memory locations of
those parameters will also be investigated.
Check the program source code and also check the output. Does the output make
sense? If it does great, if not read on and fine tune your brain.
// PROG1409.CPP
// This program demonstrates parameter memory
locations.
#include <iostream.h>
#include <conio.h>
void main()
{
int Ref1;
int Val1;
clrscr();
cout << "Address of Ref1 is " << &Ref1 << endl;
cout << "Address of Val1 is " << &Val1 << endl;
CheckMem(Ref1,Val1);
getch();
}
PROG1409.CPP OUTPUT
Variable Val1 has it own private memory location. The value stored at that
memory location is copied to the memory location of Val2. Once this copy is
made, all changes will be stored in a different memory location. The actual
parameter (in the function call) and the formal parameter (in the function
heading) each have their own memory location. Now notice that both Ref1 and
Ref2 have the exact same memory location. The value of Ref1 is not passed to
the function. A reference to the memory location of the actual parameter is
passed. This is a tremendously important difference with the call-by-value-
parameter-passing approach. The value of the actual (Ref1) parameter is not
copied in the function. It is not even passed to the function. The only thing that
the function gets is a reference to the memory location of the actual parameter.
Perhaps the name variable parameter made sense because the parameter can
change. Hopefully, this technical explanation shows that the name reference
parameter is not only appropriate, it is more descriptive than variable parameter.
From now on we shall use the name reference parameter.
Now you can see how this all works. You have been fooled. There is no
information passed to a function, altered, and then passed back. The approach is
actually much simpler and very memory efficient. What do we want? We want
any changes in the formal parameter to cause a change in the actual parameter. If
the actual parameters are a list of unsorted numbers, then we want the formal
parameters in the function to bring about a nicely sorted list. Once the process is
accomplished we want the results back at the actual parameter site. Terrific, keep
This is very slick and it might have slipped right passed you. You see, sometimes
it helps to be technical. It is normal to feel on shaky understanding ground at this
stage. No problem, read on and work with this stuff. I promise that suddenly
lights will become very bright.
Scope Revisited
Scope was explained in the last chapter. This scope business is not directly
related to the reference parameters discussed in this chapter. However, the
business at hand is to take a technical look at parameter passing. It will be helpful
to also get a better understanding of information that is stored in a program
without the use of parameters.
The program that follows was shown in the last chapter to explain the scope of
many X identifiers. Every identifier has the same name, X, but every identifier
has a different scope. We will return to this program, and this time not display the
value of each identifier, but the memory location of every X. The newly found
reference operator will accomplish this task, and you will note four different
memory locations for four X identifiers in four different scopes.
// PROG1410.CPP
// This program explains scope by looking at memory
locations.
#include <iostream.h>
#include <conio.h>
int X = 100;
void Function1();
void Function2();
void main()
void Function1()
{
int X = 300;
cout << endl;
cout << "Function1 X Memory = " << &X << endl;
if (X == 300)
{
int X = 400;
cout << endl;
cout << "Very Local X Memory = " << &X <<
endl;
}
cout << endl;
cout << "Function1 X Memory = " << &X << endl;
}
void Function2()
{
cout << endl;
cout << "Global X Memory = " << &X << endl;
}
PROG1410.CPP OUTPUT
This section has four quiz programs. Each program has a Guess function that
looks very similar to the Guess functions in the other programs. Be assured that
the functions are different and each program creates different output. It will be
very easy for you to type in the program, check the result, and then with great
bravado announce to the world the obvious answer. After all, anybody whose
brain generates enough energy for body life support systems can figure out
something so simple.
This approach may be lovely for ego stroking but it does not check if you know
what is happening. The answers to these programs are intentionally not shown.
For once, you are encouraged not to check the programs. This should be an
exercise in mental computing. Check each program out prior to the class where
these programs will be discussed. Figure the answer out by tracing through the
execution sequence. You are the computer. Your teacher will discuss the
answers of each program with you in class.
Do not get fooled by the simplicity of the programs. You need to understand
parameters very well to get the correct answers to all four programs. So look at
the programs carefully. Hopefully, these quiz programs will help to confirm or
perhaps clear up some lingering confusion.
// PROG1411.CPP
// Quiz 1
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int Number1 = 10;
int Number2 = 20;
Guess1(Number1,Number2);
cout << "Number1 = " << Number1 << endl;
cout << "Number2 = " << Number2 << endl;
getch();
}
Do not get fooled. The first few program examples are quite straight forward and
hopefully every student will get the correct answer. The later quiz programs will
become more challenging. The majority of students tend not to get all quiz
programs correct. Be warned and be careful. It is trickier than it looks.
// PROG1412.CPP
// Quiz 2
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
// PROG1413.CPP
// Quiz 3
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int Number1 = 10;
int Number2 = 20;
Guess3(Number1,Number2);
cout << "Number1 = " << Number1 << endl;
cout << "Number2 = " << Number2 << endl;
getch();
}
// PROG1414.CPP
// Quiz 4
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
int Number = 10;
Guess4(Number,Number);
cout << "Number = " << Number << endl;
getch();
}
At first this seems odd, but there is considerable logic to make sense of this
feature. The purpose of a prototype is to warn the compiler that an identifier is
going to be used of a certain function, and that the full details of that function will
come later. The prototype does provide the compiler with the necessary
parameter information. This parameter information is important because the
compiler will check if the actual and formal parameters match correctly.
This brings up an interesting point. The names of the actual and formal
parameters do not need to be the same. It is required that the function call and the
function heading contain the same number of parameters.
Prototype Fact
Prototype
void GrossPay(int HW, double HR, double &GP);
// PROG1415.CPP
// This program demonstrates that prototypes do not
require
// parameter identifiers, only parameter data types and
// an ampersand if a reference parameter is used.
// Ignore all the warnings about not using variables.
#include <iostream.h>
#include <conio.h>
#include <iomanip.h>
void main()
{
int HoursWorked; // hours worked per week
double HourlyRate; // payrate per hour
double GrossPay; // pay before deductions
double Deductions; // tax deductions
double NetPay; // total take-home pay
EnterData(HoursWorked,HourlyRate);
CompGross(HoursWorked,HourlyRate,GrossPay);
CompDeduct(GrossPay,Deductions);
CompNet(GrossPay,Deductions,NetPay);
DisplayData(HoursWorked,HourlyRate,GrossPay,Deductions,
NetPay);
getch();
}
You might wonder how it is possible that writing more is quicker. The reason has
to do with block copying. You write the prototypes, complete with identifiers,
block copy the whole lot, and paste them below the main function. Now you
remove the semicolons, adds some parenthesis, and you have a stub program that
compiles. This approach actual takes more time if you have to remove, or later
add, the parameter identifiers.
But then you knew that because I am sure you are a believer in block copying
what can be block copied. Just be careful. I have made some considerable
booboos in book writing and test writing by block copying. The efficiency of
block copying also makes duplication of mistakes more efficient.
Program modularity was introduced many chapters ago, and you have no doubt
benefited from the use of functions. In the process of using functions it is
sometimes possible to create an “unwanted” inefficiency. Calling a function takes
more execution time than executing inline code. Now breaking a program into
logical segments and calling each one of these segment will not cause a penalty in
execution time that is even noticeable.
It is another story when the same function is called thousands or even millions of
times in a program. This situation can easily happen in nested loop structures,
where deep inside the inner loop, functions are called a large number of times.
C++ allows an interesting compromise. You can make a special bargain. I will
trade you some memory for execution time. C++ can create inline functions.
These functions place the actual function code in the place of the function call.
The result is that the execution time penalty does not happen. This is very
beneficial if you have few locations with a function call, but that function call is
repeated numerous times inside a loop. On the other hand, if you have the same
function call spread many, many times all over the program, you will then get a
penalty in memory usage from all the code that is copied. Inline functions
traditionally, are very small functions, and they are frequently written on one line
of code. Do not confuse a function written on one line with an inline function.
Program PROG1416.CPP has three functions that all occupy one line.
// PROG1416.CPP
// This program demonstrates small functions written on
one line.
// These are not "inline" functions.
#include <iostream.h>
#include <conio.h>
PROG1416.CPP OUTPUT
Module1
Module2
Module3
The secret of inline functions is the reserved word inline that must precede the
function heading. Program PROG1417.CPP is almost identical to the previous
program. It does produce the same output, but this time genuine inline functions
are used.
// PROG1417.CPP
// This program demonstrates small functions written on
one line
// preceded by the inline reserved word.
// These are "inline" functions.
#include <iostream.h>
#include <conio.h>
void main()
{
clrscr();
Module1();
PROG1417.CPP OUTPUT
Module1
Module2
Module3
// PROG1418.CPP
// This program demonstrates a variety of inline
functions.
// It also demonstrates that inline functions are not
based on
// one line but the inline reserved word.
void main()
{
int Nbr1,Nbr2;
EnterData(Nbr1,Nbr2);
DisplayData(Nbr1,Nbr2,AddData(Nbr1,Nbr2));
}
PROG1418.CPP OUTPUT
12 + 13 = 25
This section title should look very suspicious. “Overloading” a function sounds
pretty strange. Is the function too large? Does the function process too much?
Does it require too much memory? These are logical questions, but they are
totally unrelated to the topic at hand. Even though we are not jumping into Object
Oriented Programming (OOP) yet, the topic of overloading is one of the
important elements in OOP.
Let us start by considering some function shortcomings. Imagine that you have
the need to swap data. Not just one type of data, but integers, characters and real
numbers. The knowledge that you have right now should lead you to a program
style similar to the one shown in program PROG1419.CPP. Three different
functions are created to swap three different types of data. Function Swap1
exchanges integers, function Swap2 exchanges characters, and function Swap3
takes care of real numbers.
// PROG1419.CPP
// This program swaps three different data types with
three
// different swap functions.
#include <iostream.h>
#include <conio.h>
void main()
This capability exists in C++, and we can accomplish the desired - single name
identifier - by using overloading. So what is overloading? It has nothing to do
with loading really. Overloading enables you to use the same program features
for different purposes. This can apply to operators and it can apply to functions.
You have already used this business with operators, and you did not give it a
second thought. Consider the following two statements:
The same ( + ) operator is used for arithmetic addition and also for string
concatenation. Computer science people would say: “The + operator is
overloaded.”
Overloading
Overloading Example:
int X,Y;
apstring First,Last,Complete;
X = 100;
Y = 200;
Sum = X + y;
// PROG1420.CPP
// This program swaps three different data types with
three
// different swap functions that all have the same
name.
#include <iostream.h>
#include <conio.h>
void main()
{
int IVar1 = 10, IVar2 = 20;
char CVar1 = 'A', CVar2 = 'Z';
double DVar1 = 1.111, DVar2 = 9.999;
clrscr();
cout << "Integers: " << IVar1 << "\t\t" << IVar2
<< endl;
cout << "Characters: " << CVar1 << "\t\t" << CVar2
<< endl;
cout << "Doubles: " << DVar1 << "\t" << DVar2 <<
endl;
Swap(IVar1,IVar2);
Swap(CVar1,CVar2);
Swap(DVar1,DVar2);
PROG1420.CPP OUTPUT
10 20
A Z
1.111 9.999
20 10
Z A
9.999 1.111
It is quite possible that the overloaded function business leaves you wondering
about all the hype. It sounds good, but the bottom line is that you still have to
write as many swap functions as there are data types to exchange. This true, but it
This gets us to the main point. How about duplicate identifier errors? It is easy to
convince yourself that this will not happen by running the program example. The
C++ compiler has no difficulty determining which function is called. The secret
is in parameter matching. Each Swap function has a different set of parameters
and choice of actual parameters in the function call determines where the program
execution continues.
The main function of the program will be shown first with the output. You will
note that the same function (at least same function identifier) is called three times
with three different actual parameter types. Three different messages result.
void main()
{
clrscr();
Display(1);
Display('A');
Display(1.1);
getch();
}
INTEGER DISPLAY
CHARACTER DISPLAY
DOUBLE DISPLAY
// PROG1421.CPP
// This program displays three different messages
depending
#include <iostream.h>
#include <conio.h>
void Display(int);
void Display(char);
void Display(double);
void main()
{
clrscr();
Display(1);
Display('A');
Display(1.1);
getch();
}
void Display(int)
{
cout << endl << endl;
cout << "INTEGER DISPLAY" << endl;
}
void Display(char)
{
cout << endl << endl;
cout << "CHARACTER DISPLAY" << endl;
}
void Display(double)
{
cout << endl << endl;
cout << "DOUBLE DISPLAY" << endl;
}
What you see here is an interesting different use of function parameters. In this
case, information is not passed to a function for any type of process. The only job
of the actual parameter is to help identify which Display function will be
executed next. The main reason for showing this program is to help understand
how overloaded functions can be properly selected.
There have been two chapters of parameter functions and a very heavy chunk of
information has been thrown at you. It is time to summarize this parameter
function business with a variety of rules. These rules are numbered only for
reference. The rule numbers have no relationship to any rule numbers that exist
in the computer science community or in C++.
Example:
Rule1(10,20,30);
Example:
Rule2(100,’A’,123.321);
Example:
Example:
Let us summarize this parameter business, with a real life analogy that may help
some students. The analogy that follows explains some of the parameter rules in
a totally different manner. Imagine that you are at a track meet and you watching
a relay race. In this relay race the starters run 100 meters and then pass a baton to
the next runner in their team.
In the first relay race example, the race official checks the track and announces
that the race is not ready. A look at Race1 shows there are four starters ready in
their lanes, but only three runners at the 100 meter baton passing mark. A runner
from the Netherlands (NL) is missing.
Race1
US US
GB GB
FR FR
NL
Race2 presents another situation with a different problem. This times the number
of runners is correct. There are four starters and there are also four runners at the
100 meter mark ready to receive a baton. However two runners at the 100 meter
mark are standing in the wrong lane. The track official announces that the race
cannot start unless the runners change lanes and are ready to receive the batons
from their own country men.
Race2
GB GB
FR NL
NL FR
Race3
US (John) US (William)
GB (George) GB (Thomas)
FR (Gerard) FR (Louis)
NL (Hans) NL (Hans)
The point of this analogy is that the names do not matter. What matters is that
there are the same number of runners at the passing mark as there are in the
starting blocks. It also matters that everybody stays in their lanes and that the
runners receiving batons are on the same team as the starters.
The batons are passed not based on the names of the runners, but
on the lanes they run in.
All the functions in this section are void functions. The concern with each
function is the resulting value of the parameter(s) in the function call. A function
with appropriate parameters is provided with each exercise.
In the trace table an & is placed in front of any reference parameter, and the
variable of the function call that references the same memory address is listed in
parenthesis.
Exercise 01
void Ex1401(int &N)
{
for (int K = 1; K < 5; K++)
if (N % 2 == 0)
N++;
else
N+=3;
}
int P = 4;
Ex1401(P);
P K N % 2 == 0 &N (P)
4 4
1 true 5
2 false 8
3 true 9
4 false 12
After Function P = 12
Call
int P = 5;
int Q = 6;
Ex1402(P,Q);
P Q &X (P) Y
5 6 5 6
15 21
After Function P = 15 Q=6
Call
Exercise 03
void Ex1403(int X, int &Y)
{
X += 10;
cout << "X = " << X << endl;
Y += X;
cout << "Y = " << Y << endl;
}
int P = 5;
int Q = 6;
Ex1403(P,Q);
P Q X &Y (Q)
5 6 5 6
15 21
After Function P=5 Q = 21
Call
int P = 5;
int Q = 6;
Ex1404(P,Q);
P Q &X (P) &Y (Q)
5 6 5 6
15 21
After Function P = 15 Q = 21
Call
Exercise 05
void Ex1405(int &X, int Y)
{
X += 10;
cout << "X = " << X << endl;
Y += X;
cout << "Y = " << Y << endl;
}
int P = 5;
Ex1405(P,P);
P &X (P) Y
5 5 5
15 20
After Function P = 15
Call
int P = 5;
Ex1406(P,P);
P X &Y (Q)
5 5 5
15 20
After Function P = 20
Call
Exercise 07
void Ex1407(int &X, int &Y)
{
X += 10;
cout << "X = " << X << endl;
Y += X;
cout << "Y = " << Y << endl;
}
int P = 5;
Ex1407(P,P);
P &X (Q) &Y (Q)
5 15 15
30 30
After Function P = 30
Exercise 08
Consider the following function.
X = 3;
Y = 6;
Hello(X,Y);
cout << X << " " << Y;
(A) 9 0
(B) 9 -1
(C) 10 0
(D) 10 -1
(E) There is no output. Function Hello never terminates.
X = 3;
Y = 6;
Hello(X,Y);
X Y &A (X) &B (Y)
3 6 3 6
4 5
Exercise 09
Consider the following function.
Answer is (E)
If B < 0 the while loop starts out as false and the function
will terminate immediately.
Exercise 10
void Ex1410(int &X)
{
int Y;
while (X < 10)
{
Y = 1;
while (Y <= 10)
{
Y++;
X += 2;
}
X += Y;
}
}
int P = 5;
Ex1410(P);
P Y X (P)
5 5
1
2 7
3 9
4 11