|
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. Functional Decomposition
2. What the function will 'receive' from any function that calls it;
3.What the function will 'return' to the calling function when
finished. This is the bare minimum to be included in the description of any
function. If you look back at chapter 3 you will find that this is the
information we included in 'main'. What was not mentioned back then is
that 'main' is a function. In the last chapter we talked about inputs and
outputs but what are these 'receives' and 'returns'? Functions, of course,
do something. To accomplish that 'something' one function may need to use
another function - in computer science terminology, one function may need
to 'CALL' or 'SEND A MESSAGE' to another function. In the process the
called function may receive data from the calling function and may return
data to the calling function. This is similar to what would happen if I
'called' you to grade a test paper for me. You would receive the test
paper and the correct answers from me and return the grade to me. It is
also what happens when the president calls a vice-president to request
that some action be performed. As part of your program design you need to determine not only what
functions are necessary, but what information must be passed back and
forth between functions. To concretize this discussion, let's continue
work on the 'Employee Salary' problem. At this point our design and
corresponding structure chart for this problem tell us which functions are
necessary. Also, the lines in the structure chart indicate function calls.
Thus, 'CalculateSalary' calls 'GetRateofPay' and 'GetHoursWorked'.
However, we have yet to determine the communication paths between
functions. In other words, we need to determine what, if anything, each
function needs to receive to accomplish its task and what, if anything,
each function will return. One way to work this out for any problem is to
ask the following two questions of each function:
2. What, if any, data does the calling function expect back?
Note that there is a subtle distinction between
the receives-returns pair and the input-output pair. When something is
input to a function, it is "sent in" from outside the program. Something
that is received by a function is sent from another part of the program -
from the "calling" function. The difference between output and return is
similar. For any function that is at all complex, programmers will often include
an algorithm. To help you understand the programming process and get
practice with good design, you may be required at first to include an
algorithm for even the simplest of functions. As your programming and
design skills improve, this requirement will be relaxed - as will some of
the others listed here. The idea is that at first you need practice
explicitly writing down your design decisions. Later, after it becomes
second nature to make them properly, it will be OK to simply do them in
your head. However, you will always need to know the purpose of a function
you are about to write, as well as its receives, returns and algorithm -
whether you write them down or not! B. Function Design and Basic Input Functions GetRateofPay So far so good and fairly obvious. The only point that might be at all
questionable is the type of the variable <rateOfPay> . (Remember
that we will use the notation <...> to represent a variable. ) Here
is the advantage of the analysis phase and a carefully developed set of
specifications. From the analysis we did of this problem back in chapter
two, we know that 'rateOfPay' involves money and therefore is of type
'double'. Now, let's ask the first of our 'receive/return' questions:
This is not some obscure, technical question and it can usually be
answered in a very practical way. For example, if your boss requests you
to go ask the first person you see on the street how much he or she is
paid by the hour (not a very wise question to ask in this day and age but
let's just pretend), do you need any further information from your boss?
No, you just go out and ask that perfect stranger how much he or she is
paid! Similarly, the 'GetRateOfPay' function does not need any information
from the 'calling' function. Therefore, we can say that it 'receives'
nothing. Now for the second question:
Again, the analysis is based on common sense. Does your boss expect any
information back from you after you ask that perfect stranger what he or
she is paid? I don't know about your boss but mine would expect to get
back the rate of pay of the person. So, one piece of data is returned -
the rate of pay. Similarly with the 'GetRateOfPay' function. Any function
that calls 'GetRateOfPay' expects to get back the rate of pay the user
enters so the function returns one item. Here is how the design looks so
far. Now for the algorithm - and it couldn't be simpler:
What this will mean in code is that we will write a prompt with a
'cout' statement and then get the input with a 'cin' statement. We
actually have a very simple but important pattern here. We actually have a
very simple but important pattern here. Whenever the purpose of a function
is to get a value from a user, we always have the same basic lines of code
- one or more 'cout's' to present a prompt and a 'cin' to input the value
requested. We also have a new kind of pattern
here - a design pattern. All functions where the purpose is to "get a
value from a user" follow the same basic design: Pattern A: Basic Input We will return to the 'Employee Salary' problem in a bit but first
let's look at a second example of this new pattern. In chapter 3 we had a
number of variations of a program where the user was to enter the price of
items to be discounted. A decomposition of this problem would lead us to
the conclusion that one of the tasks was to get the price. Since this
function has as its purpose, "to get a value from a user", it follows the
"Basic Input" pattern used in the 'GetRateOfPay' function. Here is the
design: In many of the programs you will write, there will be one or more
functions whose design will be based on the "Basic Input Pattern". In
fact, there is a second function in the Employee Salary Problem that
should use this pattern - the 'GetHoursWorked' function - see fig 4.1 and
the box "Get Employee Hours Worked". Since its design will be so similar
to what we have just seen, we will not discuss it further. However, you
might want to try it on your own. C. Function Declarations The difference between a function declaration and definition is
essentially this: in the function declaration we state the name of the
function and its receives and returns. We do not, however, include the
code for the actions of the function. They are part of the definition
because it is they that take up memory. A function can be declared any number of times - this just means that
we are announcing the existence of the function and if that announcement
takes place more than once, no big deal. However, if we define a function
twice, we are asking the system to set aside memory twice for the
instructions (code) in the function - with both memory locations referred
to with the same name, the name of the function. The problem is that when
the function is called, the system will not know which set of instructions
to execute and computers HATE ambiguity. Imagine an office complex with a big book containing procedures to be
followed for all the situations employees can encounter. Now suppose that
an employee encounters situation 'X', but when she looks up what to do,
she finds a procedure 'X' on page 25 and a different procedure 'X' on page
101. Which one should she follow? In the case of a program, we may know
that both sets of instructions are the same, but the computer will not
know this and you will get a compile error.
Enough talk, let's declare a function. We will start with
'GetRateOfPay' since we have carefully worked on its design..
The name of the function is 'GetRateOfPay'. Note that
the first letter of the name is capitalized. C++ itself does not care
whether we use upper or lower case letters but this distinguishes for the
programmer a function name from a variable name - see style sheet . In front
of the name is the type identifier 'double'. This indicates that the
function returns a double. In the design we said that GetRateOfPay returns
the rate of pay which we decided would be of type 'double'. The type of
the value returned by a function always appears in front of the function
name. We will see that some functions return nothing. In that case the
word void appears in front of the function. After the function name there is a set of parentheses with nothing
inside of them. This indicates that this function receives nothing. -
which is correct since our analysis of 'GetRateOfPay' conclude that it
received nothing. Later we will see the code for functions that do receive
data of some type.
D. Using Functions in Programs Knowing that 'main' is a function helps explain the lines:
inside the function. This function receives nothing and returns
nothing. In fact the receive/return part of the design for 'main' in our
programs will always appear as:
Inside the function 'main' there is a place where the code:
used to appear. Find this location in the original code. Note
that this code has been replaced with the single line:
This is the function call. When this line is executed, the
computer will execute the code in the memory locations where the code for
the 'GetRateOfPay' function is stored. Since the parentheses are empty,
nothing will be sent to (passed) to the function from 'main' while the
value that 'GetRateOfPay' returns will be stored in the memory location
symbolized by the variable 'rateOfPay'.
E. Function Definitions
Two points here. First, note that the error says that the symbol is
'undefined', not undeclared. The system can find the symbol but it cannot
find the definition for it - there is no address containing the code that
corresponds to the function name 'GetRateOfPay'. Second, this is not a
compiler error but a linker error. The linker is a second piece of
software that comes along after the compiler to 'link' or connect function
names with the code that is supposed to be associated with the function
name. In chapter 2 we used the phrase "the memory location associated
with...." The linker makes the connection between the name (of a function,
variable or constant) and the memory that name symbolizes or is associated
with. The instruction return is new but it does
exactly what it says - it is the function's mechanism for returning a
value. A function can only return one value using the return instruction.
If our design indicates that a function returns nothing, the return
instruction is skipped. We will see later how to return more than one
value. (The fact that functions in C++ can return no more than one value
should tip you off that these are not exactly mathematical functions.) A word about the variable 'payRate' and the
use of variables inside functions: Variables like 'payRate' that are
declared inside functions are said to be local variables. What this means
is first, that they are 'known' only inside the function. You can
visualize a function as a private room inside which some operation is
performed. If that operation requires that the operator take notes or
write down some temporary value, the outside world need not have any
knowledge about what was written down or what the operator called the
temporary value. All the outside world cares about is the value returned.
In the case of 'GetRateOfPay' the variable 'payRate' is local - the
rest of the program knows nothing about it and, indeed, a different
function in some other part of the program could also have the same
variable name. Using the same 'private room' analogy, there could be one
room in which the daily sales of vegetables are summed up and a clerk
calls the result 'theSum' and there could be another room in which the
daily sales of meat are summed up and another clerk again calls the
result, 'theSum'. As long as both clerks stick to themselves, there is no
problem with them using the same name for two different calculations. To emphasize this, it should be pointed out that we could change the
name of 'payRate' to 'rateOfPay - the variable name found in 'main'. This
was not done originally to avoid confusion on your part but the machine
does not care. It easily keeps track of the fact that one 'rateOfPay'
variable belongs to the function 'main' and one to the function
'GetRateOfPay'. The second important fact about local variables is
that they exist in memory only as long as the code in the function is
executing. Thus, only when 'GetRateOfPay' is called is memory set aside
for the local variable 'payRate'. Likewise, this memory for 'payRate' is
returned to the system when 'GetRateOfPay' executes the 'return'
instruction and stops.
One little, ugly point that gets programmers all the time: A
declaration ends with a semicolon BUT, neither the first line of a
function definition nor the whole definition, ends with a semicolon. You
can think of this as something designed just to keep you on your toes.
It is now time to put the whole program together:
Note also that the name 'GetRateOfPay' is used three
times in this program - to declare the function, to define it, and to call
it. When you write code be sure that you spell your function (and variable
as well as constant) names exactly the same each time. Remember that C++
is case sensitive
meaning that 'GetRateOfPay' is not the same as 'getRateOfPay'. F. Why Use Functional Decomposition
The fact that we have discovered a "user input" pattern for functions
like this means we have accomplished the first goal; the code is certainly
simple enough thus accomplishing the second goal; and we now explore the
third goal. Suppose that tomorrow the boss comes in and says:
You don't have to go through all the code looking for all the places
where the salary is asked for (imagine that this is a larger, more complex
program) before you can make any changes. All you need to do is find the
'GetRateOfPay' function and modify it. Here is an example of the
modifications you might make. |