Additional Material 3 Functions and parameter passing If there are a few lines of code that you find yourself repeating frequently, or that you expect to repeat frequently, it's a good idea to package those statements together, so that you can use a single name in place of that list of statements. It's even a good idea to do this if you never expect to use the name again, if those statements perform a complex task and reading them would only distract someone from the real purpose of your program. To take a collection of statements and package them together, C++ provides functions: typename functionname ( parameter list) { several statements } The typename is the type (int or double, for example) of the expression returned from the function. A function not intended to return anything is declared to return type "void". The functionname is an identifier, and must begin with a letter and avoid duplicating any C++ keywords (for, while, etc). The parameter list is a (possibly empty) comma-separated list of type/identifer pairs. For example: (int Nrabbits, double MaxRabbitWeight) The "several statements are just the statements you want to execute. Where identifiers from your parameter list appear, their initial values are the values given as arguments when the function is invoked. For a concrete example, here's an implementation of Euclid's algorithm for computing the greatest common divisor (GCD) of two nonnegative integers: unsigned GCD(unsigned A, unsigned B) { while (A > 0) { unsigned C(B%A); B = A; A = C; } return B; } The return statement provides a value to be returned from the function. Although code is most easily readible when there is a single return statement at the end of the function, you can place several of them, all over the function definition. Consider the action of this function on a simple example: A B C 72 108 36 36 72 0 0 36 Or, perhaps on this less simple example: A B C 144 89 89 89 144 55 55 89 34 34 55 21 21 34 13 13 21 8 8 13 5 5 8 3 3 5 2 2 3 1 1 2 0 0 1 To invoke the function, just use something like Z = GCD(X,Y); However, to use the function, you must give the compiler information on how it can be legally used. Suppose that you put the function definition above into GCD.cc, compile it to produce GCD.o, and accidently delete GCD.cc. What does the compiler have to see in a different C++ source file to know that you are using GCD properly? The compiler has to see in that source file a function declaration. A function definition is a declaration. And this unsigned GCD(unsigned A, unsigned B); is a declaration too. It tells the compiler that using a function called GCD with two arguments, both unsigned, is okay, and it returns an unsigned. Declarations like this are typically put in "header files", and this one would be named "GCD.h". The file that intends to use GCD would have the line #include "GCD.h" somewhere near the beginning of the file (and definitely before the first use of the GCD function). The file that defines GCD would include it too, so that the compiler can check for inconsistencies there. Note that in the definition of GCD, we modified A and B. Does this change X and Y in Z = GCD(X,Y); ? No. Because function arguments in C++ (with an exception that I won't mention for a while) are passed by value; in other words, in invoking GCD(X,Y), the parameter A is a copy of the argument X, so that the initial value of A is the value X, but changing A, as we do in the definition of GCD, does not change X. Similarly for Y and B. Consider a different function that might be mildly useful: void Swap(double R, double S) { double T(R); R = S; S = T; } If X is 1.0, and Y is 2.0, then what are the values of X and Y after Swap(X,Y); ? They are 1.0 and 2.0, still. We are still passing arguments by value, so changing parameter R does not change argument X.