As programs expand in length and complexity, they become difficult to write, read, understand, and debug. Computer scientists have learned through experience that these difficulties become less significant if programs are written in blocks, or modules. In the C++ language these modules are called functions. Functions allow you to group code into a block that can be used repeatedly.
As C developed in the early years, users wrote functions for performing standard tasks, and many of these functions have been collected in what is known as the standard library, which is included with all compilers that meet the ANSI standards.
Access to these functions is acquired by inserting header files which contain the functions' prototypes. The actual function definitions are not usually accessable to programmers, since they are pre-compiled, and in any case programmers are not likely to want to change these functions. In order to use the library functions we need only know what the function declaration looks like.
For example, in order to use the library function which calculates the square root of a number, we must either know the following:
Your text book provides a description of some of the more commonly used C++ libraries in Appendix B.
If programming could be accomplished by assembling the right library functions, programming would be a great deal simpler than it is. It would also be less exciting and stimulating (and, yes, frustrating) than it is. Almost every program that needs to be written needs some user defined functions. Writing these functions is what programming in C++ is all about.
In general, a function definition takes the form:
return_type function_name (type parameter1_name, type parameter2_name, . . .)
{
// function body
}
ExampleBelow is a small function that illustrates many of the concepts associated with functions.
double hypotenuse(double sideA, double sideB) // Definition of the // hypotenuse function { double hypot, temp; temp = sideA * sideA + sideB * sideB; hypot = sqrt(temp); // sqrt is a standard // library function return(hypot); // Returns the value of hypot } // End of program
This function definition exemplifies the following:
double hypotenuse(double sideA, double sideB);
void print_welcome() { cout << "\n" << "Hello" << endl; }
If a function has no parameters, then the keyword void may again be used.
void print_welcome(void) { cout << "\n" << "Hello" << endl; }Empty parentheses, () may be used when there are no parameters as shown above.
A function is called or invoked by a statement, referred to here as the calling statement. The calling statement usually, but not always, passes some information to the called function. The called function takes this information, performs some processing, and then usually, but not always, passes some information back to the function containing the calling statement (referred to henceforth as the calling function).
As is true of any form of communication the calling function and the called function must be in agreement about the parameters which are passed to the called function and the value which is returned to the calling function after execution of the called function.
Below is a complete program to calculate the doubling time for a population under continuous exponential growth.
// Complete program to calculate population doubling time #include <iostream.h> float doublingTime(float bacterialGrowthRate); // Prototype - notice, //it is defined before main int main () { float twiceTime, rateEColi; // data declaration rateEColi = 0.84; // Unit is bacteria per hour. Rates vary // with the environment. twiceTime = doublingTime(rateEColi); // Calling statement // rateEColi is the // actual parameter cout << "Doubling time for Escherichia coli is: " << twiceTime << endl; return 0; } float doublingTime(float bacterialGrowthRate) // Function definition - // bacterialGrowthRate is // known as a // formal parameter { float natLogOf2 = 0.6931, time2Double; // Data declarations for // doublingTime function time2Double = natLogOf2 / bacterialGrowthRate; return time2Double; }
In the example program above, note that the rate of growth of E. Coli, rateEColi, is passed to the doubling_Time function, where its value is copied and referred to by the variable name bacterialGrowthRate. Remember that the two identifiers, the name of the actual parameter and the name of the formal parameter may or may not be the same; this has no significance because the values of the actual parameters are copied to the formal parameters. This process of copying the value of the actual parameter to the formal parameter is known as PASS BY VALUE.
// This program uses the function inc_counter to increment (increase by // 1) the value of a_count. #include <iostream.h> void inc_counter(int &counter); // Function prototype int main () { int a_count=0; // Data declaration; initializes // a_count to be 0 cout << "Before the function call, a_count = " << a_count << endl; inc_counter(a_count); // Function call cout << "After the function call, a_count = " << a_count << "\n"; return 0; } void inc_counter(int &counter) // Function header { counter=counter + 1; // Increments the value of counter // which is a reference // to a_count }
Before the function call, a_count = 0 After the function call, a_count = 1
int mysubroutine(int x, char y, float z) { if (y == 'a') return(x); if (z < 3.14) return(-x); return(x*x); } int main() { int a = 1; char c = '1'; cout << mysubroutine(3, 'a', 7.1); a = mysubruotine(3, 'a', 1.2); mysubroutine(1.0, 'c', 4); c = mysubroutine(1, a, 3.2); a = mysubroutine(1, c, 3.2); }
int foo() { return(-1); } int foo() { return('1'); } int foo() { return(1.0); } int foo() { return("1"); } int foo() { ; } void foo() { ; }
For example, if the function is called like this:
print_numbers( 4, 9 );
It will print:
4 5 6 7 8 9
Write a program which calls your function a number of times to test that it is accurate.