You are on page 1of 32

Monday, October 25

th

Function Review
More on Functions
Passing Variables using References
Function Overloading and Default Parameters
Global and Static Variables
Detecting errors in functions

Function Review
int square(int x);

// int square(int);

int main(void)
{
int n;
cout << "Enter a #: ";
cin >> n;
cout << square( n ) << endl;
return(0);
}
// function definition
int square( int x )
{
int y; // new each time its called
y = x * x;
return (y);
}

1. The prototype *.
2. The function
definition:
a. Func header.
b. Formal
parameter(s)
c. Return type
d. Function body
e. Return
statement(s)
f. Local variables
3. The function
call:
a. Actual
parameter(s)

Function Review
int square(int x);

// prototype

int main(void)
{
int n;
cout << "Enter a #: "; 3
cin >> n;
4
cout << square( n+1 ) << endl;
return(0);

Things to note:
1.

All variables/
parameters in a
function are
visible only to
the function.

2. When you call a


function, the value
}
of the actual
parameters are
// function definition
copied into the
int square( int x )
formal parameters.
{
int y; // new each time its called 3. All local variables/
parameters go
y = x * x;
away when the
function exits
return (y);
}

Function Review
string nickname(int x);

// prototype

int main(void)
{
int age;
cout << "Enter your age: ";
cin >> age;
cout << nickname(age) << endl;
return(0);
}
// function definition
string nickname( int yourage )
{
if (yourage < 30)
return( kiddo );
strings!
else
return( old fogie );
}

Things to note:
1.

If a function has
a non-void return
type, it must
return a value.

2. The value returned


must have the
same type as the
return type.
3. A function may have
more than one
return statement.

Function Review
void eat(int x);

// prototype

int main(void)
{
int prunes;
cout << How many prunes? ";
cin >> prunes;
eat(prunes);
cout << aaah\n;
}

52

void eat( int num_prunes )


{
int i;

0 < 52?

for (i=0;i<num_prunes;i++)
{
if (i == 1)
return;
cout << phhhbbbbtttt\n;
}
}

Things to note:
1. A return statement
immediately exits
the function, no
matter what.

prunes 52
num_prunes 52
i 01
How many prunes?
52
phhhbbbbtttt
aaah

Function Review
// prototype:
void barf(void);
int main(void)
{
int n = 10;
barf();
cout << n;
}
// definition
void barf(void)
{
cout << n;
// OK?
n = 50;
cout << n << endl;
}

Question: Is this a valid


program?
Question: If so, what
will it print?
Question: What type of
data does the function
barf return?
Question: What type of
parameters does barf
have?

Function Review
// prototype:
void barf(void);
int main(void)
{
int n = 10;
barf();
cout << n;

Question: What will it


print?
n 10
10

}
// definition
void barf(void)
{
int n;
// local
n = 50;
cout << n << endl;
}

50
10

n 10
50

Function Review
// prototype:
void barf(void);

What will this program


print???

int main(void)
{
int x = 10;

Remember: Each time


you call a function, its
variables start fresh!

barf();
barf();
}
// definition
void barf(void)
{
int n;
cout << n;
n = 50;
}

// local

Output:

-19 37

x 10
10
n 10
-19
37
50

Function Challenge
#1. Write a function called charfind that:
A. Accepts a string parameter and a char parameter
B. Returns the index in the string of the first
occurrence of the character.
C. If the char cant be found, your function should
return -1.
void main(void)
{

#2. How can we change our


function so it finds the last
occurrence of a char in the
string?

int n;
n = charfind(hello, l);
cout << n; // prints 2
n = charfind(hello, z);
cout << n; // prints -1

Functions: Understanding
Parameters
void change_me(int x);
int main(void)
{
int n;
cout << "Enter a #: ";
cin >> n;

Questions:
1. What does this program print?
2. Does the value of n change?
3. Why or why not?

cout << n << endl;


change_me(n);
cout << n << endl;
}

// definition
void change_me(int x)
{
x = 12;
}

12
3

Enter a #: 3
3
3

Functions: Understanding
Parameters
void change_me(int x);
int main(void)
{
int n;
cout << "Enter a #: ";
cin >> n;

Ok how about this one?


Be careful!
n

cout << n << endl;


change_me(n);
cout << n << endl;
}

// definition
void change_me(int n)
{
n = 12;
}

12
3

Enter a #: 3
3
3

Functions and Reference Parameters


10

20

void swap(int a, int b)


{
int temp;
temp = a;
a = b;
b = temp;

What is it supposed to do?

10 20

}
void main(void)
{
int x = 10, y = 20;

10, 20

swap( x, y);
cout << x << endl;
cout << y << endl;
}

Whats wrong with this


program?

x
y
a
b
temp

10
20
20
10
10
20
10

Functions and Reference Parameters


The previous program was supposed to swap
mains x and y variables.
It didnt work because the swap function swaps
its own local variables and not mains variables.
So how can we let one function modify another
functions variables?
Answer: Using references!

Functions and Reference Parameters


void swap(int& a, int&
b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void main(void)
{
int x = 10, y = 20;
swap( x, y);
cout << x << endl;
cout << y << endl;
}

If you place an & between a


formal parameters type and
its name, it becomes a
reference variable.
Lets see what happens!

20 10
x 20
10
y 10
20
(ref) a
(ref) b
temp 10

Reference Parameters
You can use a reference parameter to modify
a variable from the calling function.
Any time you access the reference parameter,
youre really accessing the variable in the calling
function.
Syntax: Place an & between a parameters
type and its name in the function header:
void SomeFunction(int & doe, float & ray, string & mi)
{
etc

Functions and Reference Parameters


void cheer(string &s)
{

+ fight,

s = UCLA fight,
+ fight,

s = s + fight, ;
}

What does it print?


Lets work through it!

void main(void)
{
string msg = UCLA ";
cheer(msg);
cout << msg << endl;
cheer(msg);
cout << msg << endl;
}

UCLA fight,
UCLA fight, fight

(ref) s
msg

UCLA fight,
fight

Reference Parameters
void add4(float &x)
{
x += 4;
}
void add7(float &y)
{
y += 3;
add4(y);
}
void main(void)
{
float a = 50.0;
add7(a);
cout << 50 plus 7 is: << a;
}

Lets look at another


contrived example
(ref) x
(ref) y

53.0
50.0
a 57.0

50 plus 7 is 57.000

Functions and Reference Parameters


void zero_it( int
{
i = 0;
}

&i )

void main(void)
{
double d = 10;
zero_it(d); // SYNTAX ERROR
}

Whats wrong with it?


If youre going to pass
a value to a function
with a reference
parameter, the types
must match exactly!

The type of the reference parameter must


match exactly with the type of the argument.
In this case, were trying to pass a double
variable to an integer parameter. BAD!

Functions and Default Parameters


void fish( int eyes = 2 );
void cows(int udders = 3, int hooves = 4 );

25

void fish(int eyes)


{
cout << Fish eyes: << eyes << endl;
}
void cows(int udders, int hooves)
{
cout << Udders: << udders << endl;
cout << Hooves: << hooves << endl;
}
void main()
{
fish(5);
fish();
cows(30,3);
cows(10);
cows();
}

You can specify


default values for
function parameters
in C++. You do this in
your function
prototype.
Then, if you omit
one or more
parameters when
calling the function,
the default value(s)
are used for any
missing parameters.

Functions and Default


Parameters
void flies(int eyes, int legs = 6, int ears = 9);
You dont need
void flies(int eyes, int legs, int ears)
{
cout << Im a fly with << eyes << eyes,;
cout << legs << legs, and << ears
<< ears.;
}
void main()
{
flies(5);
flies();
}

to provide
default values
for every
parameter.

// equiv to: flies (5,6,9);


// can we call flies this way???

When you call a function with default parameters,


you still have to pass values for all non-default
parameters.

Functions and Default


Parameters
void flies(int eyes, int legs = 6, int ears = 9); Rule: All default
void spiders( int legs=4, int eyes, int noses=1);
void flies(int eyes, int legs, int ears)
{
...
}

BAD!

void spiders(int legs, int eyes, int noses)


{
...
}
void main()
{
spiders(5,6); // does it mean spiders(5,6,1);
// or spiders(4,5,6); ???
}

parameters
must be to the
right of all nondefault
parameters for
a given function.
Why? Certain
function calls
would be
ambiguous
otherwise!

Functions and Overloading


void area( int r ) {
cout << 3*r*r << endl;
}
void area( double r ) {
cout << 3.14159 * r * r << endl;
}
void area( int l, int w ) {
cout << l * w << endl;
}
void main(void)
{
int a = 5;
double b = 10;
area( a );
area( b );
area(10,4);
}

You can specify multiple


functions with the same
name that only differ by
their parameters.
The C++ compiler will
automatically figure out
which function to call based
on the types and number of
parameters you use when you
call the function.
This is called
overloading a function.
Be careful, its easy to call
the wrong function by
accident!

Functions and Overloading


// bad example
int getcircum( int rad )
{
return(2 * 3 * rad); // 2*PI*rad
}
float getcircum( int rad )
{
return(2 * 3.14159 * rad);
}
void main(void)
{
int icircum;
float fcircum;
icircum = getcirum(5);
fcircum = getcirum(6);
}

It is illegal in C++ to
overload a function JUST
based on its return type.
Overloaded functions MUST
have different parameter
types in their lists.

Variables in Functions
As weve seen, each function has its own local
variables.
A function can only access its own local variables
or those variables passed by reference.
(at least thats what weve learned so far)
Now, lets learn about two new types of
variables: global variables and static variables.

Global Variables

If you want a variable to be accessible and modifiable from


ALL functions, you can use a global variable.
int gN;

// gN is global.

void change_me(void);
void main(void)
{
cout << "Enter a #: ";
cin >> gN;
cout << gN << endl;
change_me();
cout << gN << endl;

Global variables are defined


outside of all functions.
Global variables must be
defined before they are used.
Global variables are created
before the main function
starts and initialized to ZERO!
(this is true for all standard types, e.g. int, float, etc.)

}
// definition
void change_me(void)
{
gN = -3;
}

Output:
0
gN 42
-3

Enter a #: 42
42
-3

Global Variables
#include <string>
string msg = Carey;

silly!
is

void talk(string word)


{
Careyis
+ ++ is
Carey
+ silly!
msg = msg + + word;
}
int main(void)
{
talk(is);
talk(silly!);
cout << Carey says: <<
msg;
}

You may initialize a global


variable, just like a local
variable.
The global variable is
created and initialized
before the main function
runs!

word
msg

silly
is
Carey
is silly!
is
Carey

Static Variables

Functions can have variables whose values dont disappear


every time the function exits. These are called static
variables.
The static variable is initialized
once and only once the first
time the function is called.

void ucla(void);
void main(void)
{
ucla();
ucla();
ucla();
}
cout << a;

// ERROR!

void ucla(void)
{
skip static int a = 10;

cout << a++ << endl;


}

13
12
10
11

If you do not explicitly


initialize a static variable, it
starts out with a value of 0.
Static variables, like local
variables, are only visible in the
function where they are
defined.

10 11 12

Static Variables
If you do not explicitly
initialize a static variable, it
starts out with a value of 0 the
first time the function runs.

void sum(int val);


void main(void)
{
sum(3);
sum(6);
}

Remember when your


function finishes, your static
variables dont go away!

6
3

void sum(int val)


{
skip static int total;
total += val;
cout << The sum is: <<
total << endl;
}

3
val 6
0
total 9
3

The sum is: 3


The sum is: 9

Globals, Statics and Local Variables


int careful = -10;

// global!

void hmm(void) {
int careful = 100;
cout << ++careful << endl;
}
void shh(void) {
cout << ++careful << endl;
}
void wow(void) {
static int careful = 50;
cout << ++careful << endl;
}
void main(void)
hmm();
shh();
wow();
hmm();
shh();
wow();

If a function has a local or static


variable with the same name as a
global variable, the function only
sees the local/static. (the global
variable is hidden)

What does it print?


101 -9 51 101 -8 52
careful (g) -10
-9
-8
careful (l) 100
101
101
careful (s) 50
51
52

Functions: Dealing with ERRORS!


What should you do if one
of your functions has an
error while it runs?

float Cosine(float op, float adj,


float hypotenuse )
{
float result;

To handle these cases, you


should add code to check
for errors in your logic.
And you should design each
function so it returns its
success/failure status.
Often, programmers use a
boolean return value for this:
True means success
False means failure

if (hypotenuse4/0
!= 0)
result = adj/hypotenuse;

return(result);
}
int main(void)
{

cout << Cosine(3,4,5);


cout << Cosine(3,4,0);

Functions: Dealing with ERRORS!


So how would we rewrite our
function to return an error
and the proper cosine value?

float
bool Cosine(float op, float adj,
,)
{
float &result)
hypotenuse
float result;

if (hypotenuse != 0)
{if (hypotenuse
0)
result = !=adj/hypotenuse;

Heres how we do it
1. First, lets change the
function so it returns the
result by reference.
2. Next, update the function
so it returns a boolean
result
3. Finally, update your other
functions to call the new
one properly

return(true); // success!
return(result);
}

false );

// failure!

int main(void)
{

cout
float<<c;Cosine(3,4,5);
cout << Cosine(3,4,0);
if (Cosine(3,4,0,c) == true)
cout << c;
else cout << ERROR!;

Functions: Dealing with ERRORS!


So in summary
If a function may encounter errors, it should return an
error/success status result.
All functions should check status results after calling other
functions and act appropriately.
If a boolean return value is not sufficient, you can consider
using integer values instead
int getpassword(string &pw)
{
cin >> pw;
if (pw.length() > 10)
return(1); // password is too long
if (pw.length() < 5)
return(2); // password is too short
if (pw == password)
return(3); // password is too common

You might also like