Functions

As a program grows in complexity, it becomes desirable to reduce this complexity by organizing it's code into several functions. In computer science, a function is a sequence of statements; functions are useful for preventing code duplication as well as organizing the program in a logical and understandable way.

In C++, a function is called a function. In other programming languages, it might be called "subroutine", "procedure", or "subprocedure"; these terms generally refer to the same meaning.

In C++, a function is defined in the form:

The return type is the type of the return value of the function, this is also generally known as the output of the function.

The function name is the identifier for this function.

The parameter list is a list of variable declarations delimited by commas; each variable in the parameter list is known as a parameter. When the function gets called, each parameter will be initialized to an argument that was supplied during the function call. The parameter list is also generally known as the input to the function.

The function body is a block, that is, a brace-enclosed sequence of statements; these statements will have access to the parameters from the parameter list when the function gets called and any return statement terminates the function call and provides the return value.

The simplest function to illustrate is a function that has an empty return value, empty parameter list, and an empty function body void f() {}

This function takes no input and produces no output or side effects. A side effect is any observable result or behavior of the function other than it's return value.

The type void can be specified as a return type to indicate that there is no return value of the function; void represents an empty value or the absence of a value. A function with a void return type may still have a non-empty parameter list or non-empty function body.

Here are 2 more useful functions that do have a return value:

double pi() { return 4 * atan(1); } double e() { return exp(1); }

Now within a different function, if one wanted to find the area of a circle with radius r, then the expression would be: pi() * r * r. As you already know, a function call follows the form F(A) where F is the function name and A is either empty or it is a list of arguments to assign to that function's parameters.

Since pi() only has a single return statement, then that expression would be equivalent to (4 * atan(1)) * r * r.

Of course, another function can be defined to find the area of a circle, this one having one parameter:

double circle_area(double r) { return pi() * r * r; }

Now the expression circle_area(4.0) finds the area of a circle with a radius of 4.0 (disregarding physical units). The value 4.0 is said to be the argument for the parameter named r in this function.

Here is another function that is used simply for it's side effects; it prints a horizontal line:

void hr() { cout << "=====================================================================" << endl; }

This function is quite ugly, it would more sanely be implemented using some sort of loop which you may or may not already be familiar with:

void hr() { for (int i = 0; i < 79; ++i) cout << '='; cout << endl; }

It uses a line length of 79 and a fill character of '=', it would be nice however to allow the user to override these values in a parameter list:

void hr(char fill, int length) { for (int i = 0; i < length; ++i) cout << fill; cout << endl; }

However, this implementation makes the function call more difficult since now instead of hr(), one must call it with hr('=', 79). This is where default arguments can be used:

void hr(char fill = '=', int length = 79) { for (int i = 0; i < length; ++i) cout << fill; cout << endl; }

If no argument is supplied to a parameter, then it's default value will be used as an argument; therefore hr can be called like hr(), hr('-'), or hr('#', 40).

References as parameters

A reference can be used as an argument to a function, allowing that function to modify the variable for which that reference refers to (unless it is a reference to a constant).

The following program uses a function that performs integer division, storing the quotient and remainder results into 2 variables that are each specified as a reference to int argument.

#include "std.h" void divide_int(int x, int y, int& quot, int& rem) { quot = x / y; rem = x % y; } int main() { int a, b, q, r; cout << "Enter 2 integers: "; cin >> a >> b; divide_int(a, b, q, r); cout << "After division, quotient is " << q << " and remainder is " << r << endl; }

The parameters quot and rem are referenced initialized to q and r, respectively. Any assignment to quot or rem within the divide_int function results in q or r being assigned, respectively. The argument supplied to any reference parameter must be a variable, using a literal or an expression that produces a temporary value will not compile.