Chapter 14: Functions, Blocks, and Scopes of Variables Christian Jacob

1 Procedural Abstraction by Functions 3

2 Function Prototypes 4

3 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 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 . --> 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); // complex pow(double, complex); // complex pow(complex, double); complex pow(complex, complex);

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 of C++:

int myfunc(double ); ... 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