Software Design Using C++Complex C++ FunctionsIntroductionThis section shows how to use functions that have parameters and/or return values. All of this has to do with passing data into and out of functions. (For information on functions without parameters or return values, see the section on Simple Functions.) Library FunctionsThe compiler has built-in library functions to accomplish a number of useful tasks. One such function is sqrt , which finds the square root
of a number. This function takes one parameter and also returns a value.
The parameter, given in parentheses after the function name, specifies the
value whose square root we want to find. The return value will be that
square root. Here is a typical way to call such a function:
As with any assignment statement we begin with the right hand side. The
function call passes the 1.44 to the
In this case the 1.44 is again passed to the function, which computes and returns the value 1.2. Here the 1.2 is inserted right into the output statement, so that it is printed on the screen.
Next, look at root.cpp,
a complete program that computes and prints a square root. Note that the
Writing Your Own FunctionsSee the example area3.cpp. It shows another way to divide up our area of a rectangle problem. Some of the functions used have parameters and/or a return value.
The simplest function in this program is
The
Now consider the
Let's look at the
Now look at the code for this function (inside a pair of braces, as usual).
To actually return a value, the function must use a
Finally, look at the prototype for the
It should be obvious that sending an answer back
in the function name is fine if there is just a single answer, but that
the reference parameter mechanism is needed whenever you want to send back
two or more answers. The "Return" section of the comments spell out that
parameters
The main function, reprinted below, is pretty simple. It declares some
variables and then calls the various functions to carry out the work.
First,
Let's continue examining the main function.
It is often helpful to draw pictures of our functions. The following drawing
shows a picture of each of our 4 helping functions. Each function is
pictured as a box with its name on it. The
A few notes are in order at this point. The parameters in a function call (such as those inside of main above) are called "actual parameters" while the parameters inside of a function prototype are called "formal parameters". The formal parameter names do not have to be the same as the actual parameter names, but the parameters do have to match up from left to right in terms of their type and their meaning. More advanced information about parameters can be found in the Intermediate section Functions and Parameters. Much of that information, however, is probably too advanced for those just learning to use functions.
There is clearly no need in our
area problem to subdivide things into four functions. In fact, we
previously solved the problem with only 2 helping functions and, in a
really simple version, with only a main function. For guidance on how
to subdivide a problem into functions, consider these principles.
Each function should do one central, useful task. If the function only
has one line of code in it, it is probably not too useful. If the function
has 200 lines of code in it, it is probably too long and needs to farm out
its work to helping functions or might have more than one central task,
so that it should be divided up into several functions, each of which
does just one overall task. Having just one main task for a function makes
it much clearer for the human reader of the program to follow. The name
of the function should be an indication of that main task. It is pretty
common to have a Examples Using Dark GDKDark GDK's 2D primitives allow us to output filled rectangles but do not make provision for empty ones. In order to draw an empty rectangle, we would need to draw four perpendicular lines. Now, we could put this every place in our code where this is necessary. However, that would make for a lot of repeated code - and imagine if we wanted to make a change to the logic. We would have to change it in all of the places where we used it! Therefore, let us imagine that we have a function:
This function takes the same parameters as the Dark GDK function dbBox but instead draws four lines in the current ink color. Depending on the circumstances in our program, we may already have the upper-left coordinate point as well as the rectangle's width and height. However, it may be the case that we would not want to calculate the lower right coordinates in multiple places. Though this is simple to do, it would make the code at the place of invocation look rather sloppy. Therefore, we could write a function like the one below which does the calculation and calls our main drawing function:
Finally, let us consider the possibility that we may want to draw a square, already having the upper left coordinate point and the single side-length dimension. In such a case, we could write a function like the following:
Though these are rather fabricated situations, they serve to show some interesting aspects of how we will be using functions in the future. See DrawEmptyBox.cpp for a driver program with all of these functions in it. The output of the program should appear like this. To continue with our drawing of a smiley, we can take a look at the program in SmileyBlink.cpp. This program draws a smiley to the screen, pauses, and then "blinks" the eye on the face by replacing the Ball-shaped eye with a horizontal line. The tasks of drawing the face and blinking its eye are split into different functions which are meticulously detailed in the file itself. For our purposes here, it is only important to draw your attention to the fact that the DarkGDK function (that is, the main driver function) is short and to the point because of the use of functions. Even though the function code is not being reused, it has made this program eminently readable. Related Items
|