Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
1 Procedural Abstraction by Functions 3
2 Function Prototypes 4
3 Scope Rules of Functions 7 3.1 Local Variables 8 3.2 Formal Parameters 15 3.3 Global Variables 16
4 Passing Arguments to Functions 19 4.1 Passing Pointers 19 4.2 Passing Arrays 21 4.3 Passing Strings 27
5 Command Line Arguments for main() 29 5.1 argc and argv 30 5.2 Passing Numeric Command Line Arguments 34 5.3 Converting Numeric Strings to Numbers 35
TOC 1 Back
Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
6 The return Statement 36 6.1 Returning from a Function 36 6.2 Functions Returning void 37 6.3 Returning Values 39 6.4 Returning Pointers 42
7 Reference Parameters 44 7.1 General Parameter Passing Mechanisms 44 7.2 C++ Approaches to Argument Passing 46 7.3 Call-by-Reference Using a Pointer 48 7.4 Reference Parameters 55 7.5 Returning References 59 7.6 Independent References 65 7.7 Restrictions When Using References 66
8 Overloading and Default Arguments 67 8.1 Function Overloading 67 8.2 Default Function Arguments 71 8.3 Default Arguments versus Overloading 73 8.4 Function Overloading and Ambiguity 78
TOC 2 Back
Procedural Abstraction by Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
1 Procedural Abstraction by Functions
The functional structure of the Inventory example (Chapter 12.2):
void display() void init_list()
int main() char menu() char
void enter() void update()
int int
void input(int i)
First Back TOC 3 Prev Next Last
Function Prototypes Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
2 Function Prototypes
In C++, all functions must be declared before they are used.
Typically, this is accomplished by use of a function prototype.
Prototypes specify the data interface of a function by … • its return type, • the type of its parameters, and • the number of its parameters.
Prototypes allow the compiler to perform three important operations, namely: • What type of code to generate when a function is called. Different return types must be handled differently by the compiler. • Find and report any illegal type conversions between the type of arguments used to call a function and the type of definition of its parameters. • Detect differences between the number of arguments used to call a function and the number of parameters in the function.
First Back TOC 4 Prev Next Last
Function Prototypes Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
General Form of a Function Prototype Definition
Prototype definitions have to appear before a function is used in a program.
A function prototype definition is the same as a function definition, except that no body is present: type function_name( type parameter_name_1, type parameter_name_2, ... type parameter_name_N );
Example:
void sqr_it(int *i);
The use of parameter names in a prototype is optional:
void sqr_it(int *);
First Back TOC 5 Prev Next Last
Function Prototypes Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
The following program uses a function prototype to enforce type checking:
void sqr_it(int *i); // prototype
int main() { int x;
x = 10; sqr_it(x); // Error: type mismatch
return 0; }
void sqr_it(int *i) { *i = *i * *i; }
First Back TOC 6 Prev Next Last
Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
3Scope Rules of Functions
The scope rules of a programming language are the rules that govern how an object—a variable, a data structure, a function—may be accessed by various parts of a program.
The scope rules determine … • what code has access to a variable and • the lifetime of a variable.
There are three types of variables: • local variables, • global variables, and • formal parameters.
First Back TOC 7 Prev Next Last
Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
3.1 Local Variables
Variables that are declared inside a function are called local variables.
int f() { int a, b; ... }
In this example, a and b are local variables of the function f().
int f ( ) parameters:
local: int a int b
First Back TOC 8 Prev Next Last
Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Variables can also be localized to a block1.
int f() { int f ( ) int a=1, b=2, c; parameters: cout << c = a * b; local: int a = 1 int b = 2 { int c int a=11, b=12, c=13;
cout << a * b; cout << c; local: int a = 11 } int b = 12 int c = 13 cout << a * b; cout << c; }
1. A block begins with an opening curly brace and ends with a closing curly brace.
First Back TOC 9 Prev Next Last
Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Variables can also be localized to a block1.
int f() { int f ( ) int a=1, b=2, c; parameters: cout << c = a * b; local: int a = 1 int b = 2 { int c int a=11, b=12;
cout << a * b; cout << c; local: int a = 11 } int b = 12
cout << a * b; cout << c; }
1. A block begins with an opening curly brace and ends with a closing curly brace.
First Back TOC 10 Prev Next Last Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Examples of Blocks:
A block is any code section delimeted by opening and closing curly braces:
•{ … } • if ( condition ) { … } • switch ( condition ) { … } • while ( condition ) { … } • do { … } while ( condition ) • for ( init; condition; inc_dec ) { … } • type function ( arguments ) { … } •…
First Back TOC 11 Prev Next Last Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Local variables …
• are created upon entry into a block • are local to this block • are destroyed upon exit from this block
Hence, local variables exist only while the block of code in which they are declared is executing.
… and functions
• Each function defines its own scope. • All variables needed within a function should be declared at the beginning of that function´s code block. • The variables declared within one function have no effect on those declared in another—even if the variables share the same name.
First Back TOC 12 Prev Next Last Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
float f1(int a, float b) { int f1 ( ) float c = a*b; parameters: int a, float b return c; local: float c }
float f2(int a, float b) int f2 ( ) { parameters: int a, float b c = a * b; local: - return 2*c; }
int main() int main ( ) { parameters: - float a=1, b=2, c=4; local: float a = 1 cout << f1(a,b) + f2(a,c) + c; float b = 2 return 0 float c = 4 }
First Back TOC 13 Prev Next Last Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
float c = 10; float f1(int a, float b) float c = 10 { int f1 ( ) float c = a*b; parameters: int a, float b return c; } local: float c
float f2(int a, float b) { int f2 ( ) c = a * b; parameters: int a, float b return 2*c; local: - }
int main() { int main ( ) float a=1, b=2; parameters: - cout << f1(a,b) + f2(a,c) + c;local : float a = 1 return 0 float b = 2 }
First Back TOC 14 Prev Next Last Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
3.2 Formal Parameters
If a function uses arguments, it must declare variables that will accept the values of those arguments.
These variables are called the formal parameters of the function.
• Formal parameters behave like any other local variables inside the function. • The scope of a formal parameter is local to its function.
Example:
int f(int a, float b, double *c) { ... }
This function has three formal parameters a, b, and c of type integer, float, and pointer to double.
First Back TOC 15 Prev Next Last Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
3.3 Global Variables
Global variables …
• are known throughout the entire program, • can be used by any piece of code, • maintain their values during the entire execution of the program.
The scope of global variables extends to the entire program.
Global variables are created by declaring them outside of any function.
When a global and a local variable share the same name, the local variable has precedence.
First Back TOC 16 Prev Next Last Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
float c=3;
float f1(int a, float b) { float c = a*b; return c; }
float f2(int a, float b) { c = a * b; return 2*c; }
int main() { float a=1, b=2;
cout << f1(a,b) + f2(a,c) + c; return 0}
First Back TOC 17 Prev Next Last Scope Rules of Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
float c = 3; float f1(int a, float b) float c = 3 { int f1 ( ) float c = a*b; parameters: int a, float b return c; } local: float c
float f2(int a, float b) { int f2 ( ) c = a * b; parameters: int a, float b return 2*c; local: - }
int main() { int main ( ) float a=1, b=2; parameters: - cout << f1(a,b) + f2(a,c) + c;local : float a = 1 return 0 float b = 2 }
First Back TOC 18 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
4 Passing Arguments to Functions
4.1 Passing Pointers
C++ allows to pass a pointer to a function. Then the parameter has to be declared as a pointer type.
void f(int *j) { *j = 100; }
int main() { int i; int *p;
p = &i; // p now points to i
f(p); cout << i; // i is now 100 return 0; }
First Back TOC 19 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
The pointer variable p is actually not necessary: void f(int *j);
int main() { int i;
f(&i);
cout << i;
return 0; }
void f(int *j) { *j = 100; }
First Back TOC 20 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
4.2 Passing Arrays
When an array is an argument to a function, only the address of the first element of the array is passed, not a copy of the entire array.
Note: In C++, an array name without any index is a pointer to the first array element.
This means that the formal parameter declaration has to be of a compatible type.
There are three ways to declare a parameter that is to receive an array pointer: • as an array of the same type and size as that used to call the function • as an unsized array • as a pointer
The following three example programs illustrate these three possibilities.
First Back TOC 21 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Passing Arrays (1): with size specification
void display(int num[10]);
int main() { int t[10], i;
for(i=0; i<10; ++i) t[i] = i; display(t); // pass array t to function return 0; }
void display(int num[10]) { int i;
for(i=0; i<10; i++) cout << num[i] << ‘ ‘; }
First Back TOC 22 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Passing Arrays (2): as an unsized array
void display(int num[]);
int main() { int t[10], i;
for(i=0; i<10; ++i) t[i] = i; display(t); // pass array t to function return 0; }
void display(int num[]) { int i;
for(i=0; i<10; i++) cout << num[i] << ‘ ‘; }
First Back TOC 23 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Passing Arrays (3): using a pointer
void display(int *num);
int main() { int t[10], i;
for(i=0; i<10; ++i) t[i] = i; display(t); // pass array t to function return 0; }
void display(int *num) { int i;
for(i=0; i<10; i++) cout << num[i] << ‘ ‘; }
First Back TOC 24 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Passing Array Elements
void display(int num);
int main() { int t[10], i;
for(i=0; i<10; ++i) t[i] = i; for(i=0; i<10; i++) display(t[i]);
return 0; }
void display(int num) { cout << num << ‘ ‘; }
First Back TOC 25 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Important to remember: As for arrays, only addresses are passed to a function, the function will potentially alter the contents of the array.
void cube(int *n, int num) { while(num) { *n = *n * *n * *n; num--; n++; } }
void main() { int i, numbers[10];
for(i=0;i<10;i++) numbers[i] = i+1; cube(numbers,10); for(i=0;i<10;i++) cout << numbers[i] << ‘ ‘; }
First Back TOC 26 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
4.3Passing Strings
Strings are simply character arrays that are null-terminated.
When a string is passed to a function, only a pointer to the beginning of the string (of type char *) is actually passed.
First Back TOC 27 Prev Next Last Passing Arguments to Functions Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
The following code fragment defines a function that converts strings to uppercase:
void stringToUpper(char *str);
int main() { char str[80]; strcpy(str, “this is a test”); stringToUpper(str); cout << str; return 0; }
void stringToUpper(char *str) { while(*str) { *str = toupper(*str); // one character str++; // move on to next char }}
First Back TOC 28 Prev Next Last Command Line Arguments for main() Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
5 Command Line Arguments for main()
To pass information into a program when you call it, is accomplished by passing command line arguments to the program.
A command line argument is the information that follows the program´s name on the command line of the operating system.
Examples: > ls -a > ls -la
> diff file-1 file-2
> CC program-name.cc > CC -out prog-ex-name program-name.cc
> add 123 745
First Back TOC 29 Prev Next Last Command Line Arguments for main() Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
5.1 argc and argv
C++ defines two built-in, but optional, parameters to main( ), which receive the command line arguments: • argc: an integer The argc parameter is an integer that holds the number of arguments on the command line. It will always be at least 1, because the name of the program also counts.
• argv: a pointer The argv parameter is a pointer to an array of character pointers. Each pointer in the argv array points to a string containing a command line argument: argv[0]: the program´s name argv[1]: the first argument argv[2]: the second argument …
First Back TOC 30 Prev Next Last Command Line Arguments for main() Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
The following program demonstrates how to access command line arguments. It prints hello, followed by the string entered as the first command line argument.
int main(int argc, char *argv[]) { if(argc != 2) { cout << “You forgot to type your name.\n”; return 1; }
cout << “Hello “ << argv[1] << ‘\n’;
return 0; }
Output of this program:
>name Jessica Hello Jessica >
First Back TOC 31 Prev Next Last Command Line Arguments for main() Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
The following program demonstrates how to access command line arguments. It prints hello, followed by the string entered as the first command line argument.
int main(int argc, char *argv[]) { if(argc != 2) { cout << “You forgot to type your name.\n”; return 1; }
cout << “Hello “ << argv[1] << ‘\n’;
return 0; }
Output of this program:
>name Jessica Hello Jessica >
First Back TOC 32 Prev Next Last Command Line Arguments for main() Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Command line arguments should be separated by spaces or tabs.
The following program prints all command line arguments it is called with, one character at a time.
int main(int argc, char *argv[]) { int t, i;
for(t=0; t < argc; ++t) { i = 0; while( argv[t][i] ) { cout << argv[t][i]; ++i; } cout << ‘ ‘; } return 0; }
First Back TOC 33 Prev Next Last Command Line Arguments for main() Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
5.2 Passing Numeric Command Line Arguments
All command line arguments are passed to the program as strings.
Hence, numeric arguments have to be converted into their proper internal formats. The following program displays the sum of two numeric command line arguments.
int main(int argc, char *argv[]) { double a, b;
if(argc != 3) { cout << “Usage: add num num\n”; }
a = atof(argv[1]); b = atof(argv[2]);
cout << a + b; return 0; }
First Back TOC 34 Prev Next Last Command Line Arguments for main() Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
5.3Converting Numeric Strings to Numbers
The C++ standard library, cstdlib, includes several functions that allow conversions from the string representation of a number into its internal numerical format: • atoi( ): numeric string --> integer • atol( ): numeric string --> long integer • atof( ): numeric string --> double floating-point
int main() { int i; long j; double k;
i = atoi(“100”); j = atol(“100000”); k = atof(“-0.123”);
cout << i << ‘ ‘ << j << ‘ ‘ << k << ‘\n’; return 0; }
First Back TOC 35 Prev Next Last The return Statement Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
6 The return Statement
6.1 Returning from a Function
A function returns to its calling routine either … • when the function´s closing curly brace is encountered • or when a return statement is executed.
The return statement can be used with or without an associated value.
However, functions that are declared as returning a value (with non-void return type) must return a value.
Only functions declared as void can use return without any value.
First Back TOC 36 Prev Next Last The return Statement Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
6.2 Functions Returning void
For void functions, the return statement is mostly used as a program-control structure, e.g., to prevent part of a function from executing, as the following example demonstrates.
void power(int base, int exp) { int i;
if(exp < 0) return; // No negative exponents // Bypass rest of function i = 1;
for( ; exp; exp--) i = base * i;
cout << base << “^” << exp << “ is “ << i; }
First Back TOC 37 Prev Next Last The return Statement Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
A function may contain several return statements.
void f() { // ...
switch( c ) { case ‘a’: return; case ‘b’: // ... case ‘c’: return; }
if(count < 100) return; // ... }
However, one should be careful about using too many returns, because they might confuse the meaning of the overall functional control structure.
First Back TOC 38 Prev Next Last The return Statement Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
6.3Returning Values
Every function of a non-void type has to return a value by the return statement.
Any of these value-returning functions can be used as an operand in an expression.
Examples:
x = power(y);
if(max(x, y) > 100) cout << “...”;
switch(abs(x)) { ... }
First Back TOC 39 Prev Next Last The return Statement Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Searching a substring within a string
The function returns the index of the first matching substring.
int findSubstr(char *sub, char *str);
int main(int argc, char *argv[]) { int index;
index = findSubstr(argv[1], argv[2]);
cout << “Index of “ << argv[1]; cout << “ in “ << argv[2] << “ is “; cout << index;
return 0; }
First Back TOC 40 Prev Next Last The return Statement Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
// Return index of substring or -1 if not found
int findSubstr(char *sub, char *str) { int t; char *p, *q;
for(t=0; str[t]; t++) { p = &str[t]; // reset pointers q = sub;
while(*q && *q==*p) {//check for substring p++; q++; }
// If at end of q (i.e., substring), // then a match has been found if(!q) return t; // return index of match } return -1; /* no match */ }
First Back TOC 41 Prev Next Last The return Statement Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
6.4 Returning Pointers
Functions can also return pointers, which are returned like any other data type.
The following program is a pointer version of the previous program for substring search.
char *getSubstr(char *sub, char *str);
int main(int argc, char *argv[]) { char *substr;
substr = getSubstr(argv[1], argv[2]);
cout << “Index of “ << argv[1]; cout << “ in “ << argv[2] << “ is “; cout << substr;
return 0; }
First Back TOC 42 Prev Next Last The return Statement Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
// Return pointer to substring or null // if not found
char *getSubstr(char *sub, char *str) { int t; char *p, *q,*start;
for(t=0; str[t]; t++) { p = &str[t]; start = p; q = sub;
while(*q && *q==*p) {//check for substring p++; q++; }
// If at end of q, match if(!q) return start; // return pointer // to beginning of substring } return 0; /* no match */ }
First Back TOC 43 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
7 Reference Parameters
7.1 General Parameter Passing Mechanisms
In general, programming languages can provide the following mechanisms of passing arguments to a function: • Call by Value The value of an argument is copied into the formal parameter of the subroutine. --> Changes made to the parameters of the subroutine will not affect the arguments used to call it. • Call by Name The formal parameter is textually replaced by the calling argument. • Call by Reference The address of an argument is copied into the parameter. --> Changes made to the parameter will affect the argument used to call the subroutine.
First Back TOC 44 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Example: We use the following pseudo-code for defining a function, two array elements, and a variable:
f( p ) = { i := 2; a[1] := 12; x := p }
a[1] := 10; a[2] := 11; i := 1;
Now consider a call to f( a[i] ): • Call by Value: --> f( a[1] ) = f( 10 ) = { i := 2; a[1] := 12; x := 10 } --> x := 10 • Call by Name: --> f( a[i] ) = { i := 2; a[1] := 12; x := a[i] } --> x := a[2] --> x := 11 • Call by Reference: --> f( &a[1] ) = { i := 2; a[1] := 12; x := a[1] } --> x := 12
First Back TOC 45 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
7.2 C++ Approaches to Argument Passing
In general, there are several ways that a computer language can pass an argument to a subroutine.
In C++, there are two methods of parameter passing:
• Call-by-Value The value of an argument is copied into the formal parameter of the subroutine. --> Changes made to the parameters of the subroutine will not affect the arguments used to call it. • Call-by-Reference The address of an argument is copied into the parameter. Changes made to the parameter will affect the argument used to call the subroutine.
First Back TOC 46 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Call-by-Value:
int sqr_it(int x);
int main() { int t = 10;
cout << sqr_it(t) << ‘ ‘ << t;
return 0; }
int sqr_it(int x) { x = x * x; return x; }
First Back TOC 47 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
7.3Call-by-Reference Using a Pointer
One can manually create a call-by-reference by passing the address of an argument, i.e., a pointer, to a function.
The following function, which exchanges the values of two variables, uses explicit pointers in its formal parameters.
void swap(int *x, int *y) { int temp;
temp = *x; // save the value at address x
*x = *y; // put y into x
*y = temp; // put temp, i.e., x, into y }
First Back TOC 48 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Illustration of the swap( ) function — Step 0
temp:
x: 12
y: 7
First Back TOC 49 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Illustration of the swap( ) function — Step 1
temp: 12
x: 12
y: 7
temp = *x; // save the value at address x
*x = *y; // put y into x
*y = temp; // put temp into y
First Back TOC 50 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Illustration of the swap( ) function — Step 2
temp: 12
x: 7
y: 7
temp = *x; // save the value at address x
*x = *y; // put y into x
*y = temp; // put temp into y
First Back TOC 51 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Illustration of the swap( ) function — Step 3
temp: 12
x: 7
y: 12
temp = *x; // save the value at address x
*x = *y; // put y into x
*y = temp; // put x into y
First Back TOC 52 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Here is an example code fragment how to use the swap function:
int main() { int i, j;
i = 10; j = 20;
cout << “initial values of i and j: “; cout << i << ‘ ‘ << j << ‘\n’;
swap(&i, &j);
cout << “swapped values of i and j: “; cout << i << ‘ ‘ << j << ‘\n’;
return 0; }
First Back TOC 53 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Note: A less desireable solution is using swap( ) without any references to variables, because it will work only on global variables, and only on these particular variables:
a = 12; b = 7;
void swap() { int temp;
temp = a;
b = a;
a = temp; }
First Back TOC 54 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
7.4 Reference Parameters
Instead of using pointers to manually achieve a call-by-reference, it is possible to tell the C++ compiler to automatically use call-by-reference for the formal parameters of a particular function. • A reference parameter is declared by preceding the parameter name in the function´s declaration with an &. • When a reference parameter is created, that parameter automatically refers to the argument used to call the function. • The reference parameter implicitly points to the argument.
Operations performed on a reference parameter affect the argument used to call the function, not the reference parameter itself.
There is no need to apply the & operator to an argument.
Inside the function, the reference parameter is used directly; i.e., the * operator is not necessary. In fact, it is not correct to use the * operator for reference parameters.
First Back TOC 55 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Here is a simple example to understand the use of reference parameters:
void f(int &i) { i = 10; // modifies the calling argument }
int main() { int val = 1;
cout << “Old value for val: “ << val << ‘\n’;
f(val); // pass address of val to f()
cout << “New value for val: “ << val << ‘\n’; return 0; }
First Back TOC 56 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Here is the version of the swap example, now using reference parameters:
void swap (int &x, int &y) { int temp;
temp = x; // save the value at address x
x = y; // put y into x
y = temp; // put x into y }
First Back TOC 57 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
int main() { int i, j;
i = 10; j = 20;
cout << “initial values of i and j: “; cout << i << ‘ ‘ << j << ‘\n’;
swap(i, j);
cout << “swapped values of i and j: “; cout << i << ‘ ‘ << j << ‘\n’;
return 0; }
First Back TOC 58 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
7.5 Returning References
A function can return a reference, which means, it returns an implicit pointer to its return value.
--> The function can be used on the left side of an assignment statement!
double val = 100;
double &f() { return val; // return reference to val }
First Back TOC 59 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
double val = 100;
double &f() { return val; // return reference to val }
int main() { double newval;
newval = f(); // assign value of val
f() = 99.1; // change val«s value // reference to val becomes // target of assignment return 0; }
First Back TOC 60 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Here is another example program using a reference return type:
double vals[] = {1.1, 2.2, 3.3, 4.4, 5.5};
double &change_element(int i) { return vals[i]; // reference to i-th element }
void main() { int i;
for(i=0; i<5; i++) cout << vals[i] << ‘ ‘;
change_element(1) = 523.9; // second element change_element(3) = -98.7; // 4th element
for(i=0; i<5; i++) cout vals[i] << ‘ ‘; }
First Back TOC 61 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
A Solution for Safe Arrays with Bound Checking:
int &put(int i); // put value into the array int get(int i); // obtain a value from array
int vals[10];
int main() { int i;
put(0) = 10; // put values into the array put(1) = 20; put(9) = 30;
cout << get(1);
put(12) = 1; // Out of bounds return 0; }
First Back TOC 62 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
// Put a value into the array int &put(int i) { if(i >= 0 && i < 10) return vals[i]; // return ref. to ith elem. else cout << “Bounds Error!\n”; return -1; }}
// Get a value from the array int get(int i) { if(i >= 0 && i < 10) return vals[i]; // return value of ith elem else cout << “Bounds Error!\n”; return -1; }}
First Back TOC 63 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Mind the Scope of References!
When returning a reference, one has to be careful that the object being referred to does not go out of scope:
// Error: cannot return reference to local var
int &f() { int i = 10; return i; }
First Back TOC 64 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
7.6 Independent References
C++ allows to declare a stand-alone reference variable1.
An independent reference must point to some object, i.e., the reference must be initialized when it is declared.
int main() { int j, k; int &i = j; // independent reference // i is just another name for j
j = 10;
k = 121; i = k; // copies k«s value into j
return 0; }
1. Do you remember using reference parameters earlier in Chapter 8.3.2, Reference Declarations ?
First Back TOC 65 Prev Next Last Reference Parameters Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
7.7 Restrictions When Using References
There are some restrictions that apply to reference variables: • You cannot reference a reference variable. • You cannot create arrays of references. • You cannot create a pointer to a reference. • You cannot apply the & operator to a reference. • (References are not allowed on bit-fields.)
First Back TOC 66 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
8 Overloading and Default Arguments
8.1 Function Overloading
In C++, two or more functions can share the same name, as long as their parameter declarations are different.
The functions that share the same name are said to be overloaded.
Function overloading is one way that C++ achieves polymorphism.
void f(int i); void f(int i, int j); void f(double k);
void main() { f(10); // call f(int) f(10, 20); // call f(int, int) f(12.3); } // call f(double)
First Back TOC 67 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Overloading the square function:
int square(int value) { return (value * value); }
float square(float value) { return (value * value) }
void main() { cout << square(10); cout << square(12.0); cout << square(1.1); }
First Back TOC 68 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Overloading the xy power function:
// Here are the pow function prototypes
int pow(int, int);
double pow(double, double); //
First Back TOC 69 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Overloading does NOT work for return types:
It would be nice to define the string-conversion function for command line arguments as follows:
int stringToNumber(char *str) { return atoi(str); }
long int stringToNumber(char *str) { return atol(str); }
double stringToNumber(char *str) { return atof(str); } However, this is NOT possible in C++!
First Back TOC 70 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
8.2 Default Function Arguments
In C++, any function parameter can be given a default value.
The default value would be used when no argument corresponding to that parameter is specified in a function call.
Default arguments can be used to simplify calls to complex functions.
void myfunc(double num = 0.0, char ch = ‘X’) { ... }
myfunc(198.234, ‘A’); // pass explicit values
myfunc(10.3); // value for num, let ch default
myfunc(); // let both num and ch default
First Back TOC 71 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Mind the order of default values and non-defaulting parameters:
• Non-defaulting parameters first!
void f(int, int = 0, char* = 0); // OK
void f(int a = 1, int b); // error!
• No non-defaulting parameter can follow after a default parameter:
void g(int =0, int =0, char*); // error!
int f(float f, char *str, int i=10, int j);
• Be careful with blanks!
int h(int =0, int =1, char*=0); // error!
int h(int =0, int =1, char* =0); // OK
First Back TOC 72 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
8.3Default Arguments versus Overloading
Default arguments can be used as a shorthand form of function overloading.
Imagine we want to create two customized versions of the standard string concatenation function strcat( ): • One version operating like strcat( ) • The other version taking a third argument that specifies the number of characters to concatenate.
Here are their prototypes1:
void mystrcat(char *s1, char *s2, int len);
void mystrcat(char *s1, char *s2);
1. We could also use function overloading here, but using default arguments is the shorter way to do it.
First Back TOC 73 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
A customized version of strcat( ):
void mystrcat(char *s1, char *s2, int len=0);
int main() { char str1[80] = “This is a test”; char str2[80] = “123456789”;
mystrcat(str1, str2, 5); cout << str1 << ‘\n’;
strcpy(str1, “This is a test”;
mystrcat(str1, str2); cout << str1 << ‘\n’;
return 0; }
First Back TOC 74 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
void mystrcat(char *s1, char *s2, int len) { while(*s1) s1++; // find end of s1
if(len == 0) len = strlen(s2);
while(*s2 && len) { *s1 = *s2; // copy a character s1++; s2++; len--; }
// This version has a bug! }
First Back TOC 75 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
void mystrcat(char *s1, char *s2, int len) { while(*s1) s1++; // find end of s1
if(len == 0) len = strlen(s2);
while(*s2 && len) { *s1 = *s2; // copy a character s1++; s2++; len--; }
// This version has a bug! }
First Back TOC 76 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
void mystrcat(char *s1, char *s2, int len) { while(*s1) s1++; // find end of s1
if(len == 0) len = strlen(s2);
while(*s2 && len) { *s1 = *s2; // copy a character s1++; s2++; len--; }
*s1 = ‘\0’; // null terminate s1 }
First Back TOC 77 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
8.4 Function Overloading and Ambiguity
Using function overloading, it is possible to create a situation in which the C++ compiler is unable to choose between two (or more) correctly overloaded functions.
These so-called ambiguous statements are errors. Programs containing ambiguity will not compile.
Most of the ambiguity errors are caused by the automatic type conversion of C++:
int myfunc(double d); ... cout << myfunc(‘c’); // not an error, // conversion applies
First Back TOC 78 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Here the ambiguity is caused by an indeterminate type of argument:
float myfunc(float i);
double myfunc(double i);
int main() { // unambiguous: calls myfunc(double) cout << myfunc(10.1) << “ “;
// ambiguous: convert to float or double? cout << myfunc(10);
return 0; }
First Back TOC 79 Prev Next Last Overloading and Default Arguments Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob
Here is another example that causes ambiguity by using default arguments:
int myfunc(int i);
int myfunc(int i, int j = 1);
int main() { cout << myfunc(4, 5); // unambiguous
cout << myfunc(10); // ambiguous
return 0; }
int myfunc(int i) { return i; }
int myfunc(int i, int j) { return i*j; }
First Back TOC 80 Prev Next Last