Programs are composed of functions, which are, in turn, made up of statements. Functions are named blocks of code which carry out an action, or calculate a value. In a previous lesson you used math functions in <cmath>, and I/O objects and functions from <iostream>. Now you're going to write some of your own.
Let's start with some vocabulary:
- Declaring a function: specifying the function name, type and parameter types. Also called a prototype.
- Defining a function: specifying the calculations (or actions) that take place when the function is used. The actions are C++ statements that appear inside the body of the function, which is surrounded by curly braces.
- Calling a function: executing, running or invoking the function. Write the name of the function, followed by a list of arguments enclosed in parentheses. This allows the caller to pass information to the function. When the function is done, it returns to the caller, possibly supplying a value.
Once a function has been defined, other parts of the program can run that code by using the function name; there is no need to repeat the code in different places.
Here are the syntax rules for defining functions.
{
... body ...
}
- type is the kind of value returned by the function
- name is the function name used when calling it
- parameters are a list of variable declarations separated by commas, giving the type and name of each input to the function.
Here is an example function convert, from the f2c program which you saw earlier:
double convert(double temp)
{
return (temp - 32) * 5.0 / 9.0;
}
- The type of this function is double.
- The name of the function is convert.
- The function has one parameter of type double.
A parameter (aka formal parameter) is a placeholder for one of the arguments (aka actual parameters), supplied in the function call. It acts like a local variable.
Each parameter is initialized at the time the function is called, using a copy of the value of its corresponding argument. Matching is done by position, and not by name. If a function has no parameters, the parameter list in the header is empty.
The body of the function is a block consisting of the statements that implement the function, along with the declarations of any local variables. For functions that return a value to their caller, at least one of those statements must be a return statement:
return expression;
Executing the return statement causes the function to immediately to return to its caller, passing back the value of the expression as the value of the function.
Functions that return a value to their caller are called fruitful functions, because they can be treated as an operand in expressions. Functions can return values of any type. Once you have defined a fruitful function, it can be used as if it were a value. For instance, the f2c program calls convert() like this:
double celsius = convert(temperature);
In this case temperature is the argument that is used to initialize the parameter temp.
Functions do not need to return a value. Such a function is often called a procedure. Procedures must have some kind of side-effect, such as printing, to be useful.
To define a procedure, use void as the function's return type. Procedures ordinarily finish by reaching the end of the statements in the body, but you may leave the procedure early by executing a return statement by itself.
Two C++ Function Pitfalls
- Unlike Java and C#, unreachable code is not illegal. (It is a bug, though!)
- If you forget to add a return statement to a fruitful function, your code will still compile. The actual returned value will be random. This may cause your program to crash, or simply act erratically.
Functional Decomposition
To practice with functions, let's revisit Homework 00.
A metric ton is 35,273.92 ounces. Write a program that will
read the weight of a package of breakfast cereal in ounces and output the weight
in metric tons as well as the number of boxes needed to yield one metric ton
of cereal.
--Savitch, Absolute C++ 5th Edition, Chapter 2
On the next page, you'll see the main
function for an IPO program, which starts by
calling functions for input, output and processing.
int main()
{
printTitle();
double ouncesPerBox = getInput();
double tons = ouncesToTons(ouncesPerBox);
double boxes = boxesPerTon(tons);
printResults(tons, boxes);
return 0;
}
This method, starting at the highest level, and breaking the program into smaller and smaller functions, is called top down design or procedural decomposition.
The functions don't yet exist, but we can declare (or prototype) them right before the main function starts like this:
void printTitle();
double getInput();
double ouncesToTons(double ouncesPerBox);
double boxesPerTon(double tonsPerBox);
void printResults(double tons, double boxes);
Function Definitions
Once you have done that, make a copy of the prototypes following the main function. Replace each of the semicolons with a function body. Then, copy the original code (from your homework solution) into the appropriate body, and your program will work.
Here's a link to my version of this program if you want to compare it to yours.