Design with Functions
|
Table of Contents
Learning C++:
An Index of Entry Points
2. The A reference document on the basic elements of C++.
3. The Patterns
|
A. Redesigning the Employee Salary Problem
This module could then have been further decomposed into the two
modules we originally discovered. Our structure chart would then have
looked like:
In some ways this is a better approach since it captures the very
common process of developing a high level decomposition, followed by a
refined decomposition. Unfortunately, this approach can not be implemented
in C++ given what you know. Ask yourself the question, "What should
'GetEmployeeInformation' return to its calling function?" The answer is
the hours worked and the rate of pay - two values. As we have seen,
however, functions can only return one value using the normal mechanism.
You are about to learn more about how function parameters work and a bit
of 'magic' that will be further explained in chapter 7. Focus on the new
information and just accept the magic for now. B. How Parameters Work
and therefore 'rate' and 'hours' are formal parameters. On the calling
side, we wrote:
so 'rateOfPay' and 'hoursWorked' are the actual parameters. The formal parameters we have worked with so far have acted as one way
streets or one way communication paths. Information is only passed from
the calling function to the called function or from the actual to the
formal parameters but not back. In this example a value was assigned to
'rateOfPay' and, likewise, to 'hoursWorked' in 'main'. These variables
were then used as actual parameters to pass their values to the formal
parameters 'hours' and 'rate'. When a function has multiple parameters, the first value in the actual
parameter list is passed to the first value in the formal parameter list,
the second to the second, etc. The names have nothing to do with the way
the values are passed. In fact, if we had messed up and written the
function call as:
the first actual parameter, 'hoursWorked', would have sent its value to
the first formal parameter, 'rate'. The variable 'rate' in the function
'CalculateSalary' would have held the hours worked! OOPS!!! Of course,
'hours' would have held the rate of pay - for a double OOPS! The moral of
the story: Don't think that the compiler cares a bit about the names you
give to your parameters. You must be careful then with the way you code parameters. In this
case, you would have received no error message from the compiler but your
program sure would have provided funny answers. Another reason to
your code. C. Using Parameters to Return Values
and the declaration would be:
If we assume that the user entered the values 6.25 for the 'rateOfPay'
and 38 for 'hoursWorked' the following might be a stylized view of memory
after the parameter values were passed but before any of the code in the
function had executed.
Note that there are two memory locations labeled 'rateOfPay' and two
labeled 'hoursWorked' - one set for 'main' and one for 'CalculateSalary'.
Then, suppose that for some, silly reason we include the line:
inside the function definition for 'CalculateSalary'. When this line
was executed, memory would look as follows:
The interesting thing is that the 'local' version of 'rateOfPay' gets
this new value BUT the variable with the same name in 'main' retains its
old value. In other words, the code we write in the function
'CalculateSalary' has no effect on the variables in 'main'.
What you need to understand is that, given what you have seen so
far, there is no way to change a variable contained in one function
through an instruction executed in another function - except via the
'return' instruction. And, since the 'return' instruction only allows one
value to be returned, we seem to be stuck with regard to the
'GetEmployeeInformation' function.
There is, however, a solution. If we rewrite the function declaration
above as:
(note the ampersand after the word 'double' ), the picture of memory
changes. Now, and here is the magic that we won't explain until later, there
is only one memory location labeled 'rateOfPay' and it is used by both
'main' and 'Calculate Salary'.
Now, if again we include the same instruction
inside the function definition, the variable in both places (the
functions CalculateSalary and 'main') has its value changed. As a matter
of fact, as we just noted, there are no longer two variables - two separate
memory locations with the symbolic name 'rateOfPay'. Instead, there is one memory location with two symbolic names. The previous statement may be confusing because there seems to be only one symbolic name, "rateOfPay". Consider the original function declaration (where the first formal parameter has the symbolic name 'rate' instead of 'rateOfPay') and add the ampersand:
When this function is called, there is still only one memory location for the rate of pay - as shown in figure 4.6a. It simply has two symbolic names (like nicknames).
Therefore, if we include the line: in the function definition, the result is that 'rate' in
'CalculateSalary' and 'rateOfPay' in 'main' both contain the same value,
3.3! ! (Figure 4.6b) In other words, the ampersand forces the first parameter pair (formal
and actual) to act as a two-way street. Information can move both ways.
(As we said earlier, for now treat this as magic unless you want to jump
ahead to chapter 7.) In case you are wondering, Figure 4.6c shows how memory looks when the call to "CalculateSalary" returns. D. Declaring 'GetEmployeeInformation' to Return Two
Values We declare the function with two formal parameters, each with an
ampersand following the type name, as in:
Since the 'return' mechanism is not used, the function return type is
'void' The ampersands tell the system to treat both formal/actual
parameter pairs as two-way streets, allowing information to pass both
ways. Actually, since 'GetEmployeeInformation' does not receive any
information we don't need to send any information to the function but it
is not possible in C++ to set up a one way only heading back from the
function. We have a two way street where in one direction garbage is sent.
(See the commentary below the following code for further discussion of
this 'garbage'.) To finish up this process, here is the code - first, the segment of the
code for 'main' that calls this function and second the code for the
definition for this function: Note that 'GetEmployeeInformation' does not care how the information is
retrieved from the two 'Get....' functions, just that it is retrieved. At
the other end, 'main' calls GetEmployeeInformation over and over inside
the 'for' loop, not caring how 'GetEmployeeInformation' performs its task.
The first time through the loop the variables 'rateOfPay' and
'hoursWorked' have garbage in them that is passed to
'GetEmployeeInformation'. This means that the variables 'rate' and 'hours'
also contain garbage when 'GetEmployeeInformation' is called since they
are nicknames for 'rateOfPay' and 'hoursWorked' . This is not a problem,
however, because these garbage values are never used. The code says that
'rate' and 'hours' are simply given new values which, in turn, means that
'rateOfPay' and 'hoursWorked' also have new values. On each subsequent pass through the loop, 'rateOfPay' and 'hoursWorked'
have the values for the previous employee and this information is passed
to 'GetEmployeeInformation'. Again, however, this is irrelevant because
this information is not use by 'GetEmployeeInformation' and the memory
locations holding this information immediately have the information for
the next employee placed in them. If this is not clear, consider the following, perhaps slightly
stretched, example to clarify the situation. Imagine that you are employed
by someone to gather information on students. The person who has hired you
wants to gather information that she then uses in some way before throwing
it away. The person gives you a box into which you are to put some papers
containing the information on the first student. The box has some garbage
in it which you throw away and replace with the papers with the
information on the first student. You give the box back to the person who
hired you, she looks at it, does something with the information, and then
passes you back the box for the next student. The box still contains the
information from the previous student so you throw it away, gather the
information on the next student and again return the box. This continues
some number of times until the person who hired you is finished. A program that uses the function GetEmployeeInformation can be found in
the file ch4prg2.cpp. Be sure you see how
this example relates to the interplay between 'main' and
'GetEmployeeInformation'. |