ADVANCED
PLACEMENT Computer Science - C++
Lesson
6 - Functions and Scope
INTRODUCTION:
Programs of any significant size are
broken down into logical pieces called functions.
It was recognized long ago that programming is best done in small
sections which are connected in very specific and formal ways.
C++ provides the construct of a function, allowing the programmer to
develop new functions not provided in the original C++ libraries.
Breaking down a program into blocks or sections leads to another
programming issue regarding identifier scope.
Also, functions need to communicate with other parts of a program which
requires the mechanics of parameter lists and a return value.
The key topics for this lesson are:
A.
Writing Functions in C++
B. Value Parameters
and Returning Values
C. Scope of
Identifiers
VOCABULARY:
1. FUNCTION
DECLARATION |
5. VALUE PARAMETERS |
9. FUNCTION DEFINITION |
2. PARAMETERS |
6. ACTUAL ARGUMENTS |
10. GLOBAL SCOPE |
3. BLOCK |
7. FORMAL ARGUMENTS |
11. SCOPE |
4. LOCAL SCOPE |
8. LEAST PRIVILEGE |
|
DISCUSSION:
A.
Writing Functions in C++
1.
A function is like a box which takes data in, solves a problem, and
usually returns a value. The
standard math functions follow this pattern:
sqrt (2) --->
1.414
2.
There are times when the built-in functions of C++ will not get the
job done. We will often need to
write customized functions which solve a problem using the basic tools of a
programming language.
3.
For example, suppose we need a program which converts gallons into
liters. We could solve the
problem within function main.
Program 6-1
#include <iostream.h>
main ()
{
double
gallons, liters;
cout << "Enter an amount of gallons ---> ";
cin >> gallons;
liters = gallons * 3.785;
cout << "Corresponding amount in
liters = " << liters << endl;
return 0;
} |
This works fine, but the mathematics of the conversion is buried inside
function main. The
conversion tool is not available for general use.
We are not following the software engineering principle of writing code
which can be recycled in other programs.
4.
Here is the same routine coded as a reusable function
Program 6-2
#include <iostream.h>
double
convert (double amount);
// function
prototype
main
()
{
double
gallons, liters;
cout << "Enter an amount of gallons ---> ";
cin >> gallons;
liters = convert (gallons);
cout << "Corresponding amount in
liters = " << liters << endl;
return 0;
}
double
convert (double
amount)
// function definition
{
return
amount * 3.785;
} |
Sample run output:
Enter an amount of gallons ---> 10
Corresponding amount in liters = 37.85
Here is a sample showing the intro function, which is
required in all future programs.
//Program cfunctions,#9 by R. Krane on 10/12/99
#include <iostream.h >
int intro(); // prototype
double convert (double amount);
int main()
{
intro();
double gallons, liters;
cout << "Enter an amount of gallons ---> ";
cin >> gallons;
liters = convert (gallons);
cout << "Corresponding amount in liters = " << liters <<endl;
return 0;
}
int intro()
{
cout << "Program Cfunctions by R. Krane on 10/12/99" << endl;
cout << endl;
cout << "This program will convert gallons to liters." << endl;
cout << endl;
return 0;
}
double convert(double amount) //function definition
{
return amount * 3.785;
}
5.
Here is the sequence of events in this short program.
a.
Execution begins in function main with the user prompt and the input
of an amount of gallons.
b. The function convert
is called and the amount of gallons is passed as an argument to function convert.
c. Program
execution moves to function convert which solves the math and returns
the answer to the calling statement.
d. The answer is
printed out.
6.
The general syntax of a function declaration is
return type name
of function (parameter
list)
a.
The return type must be a data type already recognized by the
compiler.
b. The name of the
function must be a valid identifier.
c. The
parameter list consists of one or more type-identifier pairs of information.
These parameters are called the formal parameters.
7.
The line above function main
double
convert (double);
// function prototype
is called the function declaration or prototype.
This statement declares the
function before it is referred to in
function main. When the compiler
encounters
the line inside of function main
liters = convert (gallons);
it has already seen convert defined in the prototype.
The function definition at the bottom of the program completes the
function which must include both the prototype and code which solves the
problem. We could have placed the
function definition above function main and omitted the function declaration,
but this is good practice for later issues regarding program design in C++.
8.
When writing the function prototype, the identifier of a variable
type in the parameter list can be omitted.
The compiler will ignore any identifier names in the parameter list
of a function prototype.
9.
When the function is called, the value passed to the function is
called the actual parameter. The
integer named gallons inside of function main serves as the
actual parameter.
B.
Value Parameters and Returning Values
1.
The values passed to a function become the source of input for the
function. Notice that inside of
function convert, no data input was required from an external source.
2.
The single parameter is an example of a value parameter.
A value parameter has the following characteristics:
a.
It receives a copy of the argument which was passed to the
function. The value of 10
stored in gallons (inside of main) is passed to the parameter amount
(inside of convert).
b.
This value parameter is a variable which can be modified within the
function.
c.
This value parameter is a local variable.
This means that it is valid only inside of the block in which it is
declared. We refer to a
function in C++ as a block of code.
3.
A function can return a single value.
The data type of the value returned is listed first in the function
prototype. If this data type is
omitted the default value returned is an integer. Somewhere in the body of
the function there must be a return statement if we want the function
to return the correct answer.
4.
If a function returns no value the term void should be used.
For example:
void
printHello ( )
{
cout << "Hello world" <<
endl;
}
The term void can be used in one or both locations of input and
output for the function. However,
an alternative to a void parameter list is the empty parameter list as used in
the above example.
5.
A function can have multiple parameters in its parameter list.
For example:
double
doMath (int a,
double x)
{
... code ...
}
When this function is called, the arguments fed to function doMath
must be of an appropriate type. The
first argument must be an integer. The
second argument can be an integer (which will be promoted to a double), but it
will most likely be a double.
doMath (2,3.5);
// this is okay
doMath (1.05, 6.37);
// this will not compile
6.
Value parameters are often described as one-way parameters.
The information flows into a function but no information is passed
back through the value parameters. A
single value can be passed back using the return statement, but the actual
parameters in the function remain unchanged.
7.
The actual arguments used to supply values for the value parameters
can be either literal values (2, 3.5) or variables (a, x).
doMath (a, x);
// example using variables
C.
Scope of Identifiers
1.
Scope refers to the area of a program in which an identifier is valid
and has meaning.
2.
There are four categories of scope in C++:
file scope, block scope, function scope, and function-prototype
scope.
3.
An identifier declared outside of any function has file scope.
Such an identifier can be used in all functions which follow until
the end of the file. Such
variables are also called global variables.
The function prototypes declared near the top of a source code have
file scope.
See
Handout H.A.6.1, Scope and Value Parameters
,
to reinforce scope concepts.
|
4.
Global constants are often used in programs but global
variables are usually inappropriate.
The use of global variables can lead to difficult bugs,
therefore such use is discouraged.
|
5.
Block scope applies to identifiers declared inside a block.
A block begins wherever that identifier is declared until the
terminating right brace (}) of that block.
Functions have two possible categories of identifiers with block
scope.
a.
Function parameters have block scope.
The local identifiers used as parameters are known throughout the
function.
b.
Local variables declared inside the function have block scope.
If a block is nested inside another block, identifiers declared in the
inner block only have meaning inside the inner block.
The outer block does not have access to the inner identifiers.
For example:
Program 6-3
#include <iostream.h>
main ()
{
int
a = 3;
cout << "The value of a in the outer block = "
<< a << endl;
{
int
a = 8;
cout << "The value of a in the inner block = "
<< a << endl;
}
cout << "The value of a in the
outer block is still " << a << endl;
return 0;
} |
Run output:
The value of a in the outer block = 3
The value of a in the inner block = 8
The value of a in the outer block is still 3
6.
Identifiers used in the parameter list of a function prototype have
no meaning elsewhere in the program, even in the definition of the function.
Identifiers used in the parameter list of a function prototype are
ignored by the compiler.
7.
C++ provides the unary scope resolution operator (::) which allows
access to a global variable having the same name as a local variable.
Program 6-4
Unary Scope Resolution Operator
#include <iostream.h>
int
a = 3;
// global version of a
main ()
{
int
a = 5;
// local version of a
cout << "Local a = " << a <<
endl;
cout << "Global a = "
<< ::a << endl;
return 0;
}
|
Run
Output:
Local a = 5
Global a = 3
This unary scope resolution operator will be used when programming
classes in Lessons 12 and Lessons 27-29.
Syntax/correctness issues
6-1
The data type of the return value of a function must match the data
type in the function prototype.
6-2
Forgetting to return a value from a function, which is supposed to
return one, will lead to unexpected errors in a program.
6-3
In a function prototype, the parameter must include the data types of
values to be passed; identifiers are optional.
Also, each function prototype must end with a semicolon.
int doSomething
(int x,y);
// syntax error, the y
needs a data type
int doItRight
(int x, int y);
// this is acceptable
int P (int,
int);
// this is also acceptable
6-4
When writing the function definition, do not place a semicolon after
the parameter list.
int doItRight
(int x, int y);
// <--- no semicolon on
this line, this will not compile
{
// some code
}
6-5
Do not define a function inside another function.
C++ does not allow for nested definitions.
6-6
Function prototypes are required in C++.
Formatting suggestions
6-7
Separate the implementation of functions with blank lines to enhance
their readability.
Software engineering
6-8
Function main should consist of calls to other functions which
accomplish the work of the program.
6-9
Each function should solve a single, well-defined task.
The name of the function should help describe the task of the function.
6-10
Functions should be no longer than one page.
If possible, keep functions short.
This will make it easier to read and debug your code.
6-11
A function which contains a large number of parameters may be trying to
do too much. Consider breaking
the function down into smaller functions.
6-12
Global variables should be avoided as they allow side-effects to occur.
A side-effect is an unintended change to a global variable from inside
a function. Variables which exist
during the entire execution of the program should be declared in function main
and then passed to other functions through parameters.
SUMMARY/REVIEW:
Your programs will grow in size and complexity.
Initially you will not use all the tools presented in this lesson and
Lesson 7 regarding functions. However,
you need to see and understand all the function-writing tools in C++ since
eventually you will need them in your own work and to help you read another
programmer's code.
ASSIGNMENT:
Lab
Exercise, L.A.6.1, Fun