Chapter three
Functions
3. What is a function?
A function provides a convenient way of packaging a computational
recipe, so that it can be used as often as required.
Therefore, a function is a block of code designed to tackle a specific
problem.
• Function - a subprogram that can act on data and return a value
• Every C++ program has at least one function, main(), where program execution
begins
• A C++ program might contain more than one function.
• Functions may interact using function call
• Functions in C++ come in two varieties:
– user-defined
– built-in
• E.g pow(), sqrt(), cin, etc
3.1. Function Basics
One of the best ways to tackle a problem is to start with the overall
goal, then divide this goal into several smaller tasks. You should never
lose sight of the overall goal, but think also of how individual pieces
can fit together to accomplish such a goal.
If your program does a lot, break it into several functions. Each
function should do only one primary task.
Summarized function basics.
C++ functions generally adhere to the following rules.
1. Every function must have a name.
2. Function names are made up and assigned by the programmer
following the same rules that apply to naming variables. They
can contain up to 32 characters, they must begin with a letter,
and they can consist of letters, numbers, and the underscore (_)
character.
3. All function names have one set of parenthesis immediately
following them. This helps you (and C++ compiler)
differentiate them from variables.
4. The body of each function, starting immediately after
parenthesis of the function name, must be enclosed by braces.
3.2. Declaring, defining and calling functions
Declaring function:
o The interface of a function (also called its prototype) specifies how
it may be used. It consists of three entities:
o The function return type. This specifies the type of value the
function returns. A function which returns nothing should have a
return type void.
o The function name. this is simply a unique identifier
o The function parameters (also called its signature). This is a set of
zero or more typed identifiers used for passing values to and from
the function.
Defining a function:
o A function definition consists of two parts: interface (prototype) &
body. The brace of a function contains the computational steps
(statements) that computerize the function. The definition consists
of a line called the decelerator.
o If function definition is done before the main function, then there is
no need to put the prototype, otherwise the prototype should be
scripted before the main function starts.
Calling the function:
o Using a function involves ‘calling’ it.
o Calling a function means making the instruction of the function to
be executed.
o A function call consists of the function name followed by the call
operator brackets ‘()’, inside which zero or more comma-separated
arguments appear. The number and type of arguments should
match the number of function parameters. Each argument is an
expression whose type should match the type of the corresponding
parameter in the function interface.
o When a function call is executed, the arguments are first evaluated
and their resulting values are assigned to the corresponding
parameters. The function body is then executed. Finally the return
value (if any) is passed to the caller.
A function call in C++ is like a detour on a highway. Imagine that you
are traveling along the “road” of the primary function called main().
When you run into a function-calling statement, you must temporarily
leave the main() function and execute the function that was called. After
that function finishes (its return statement is reached), program control
returns to main(). In other words, when you finish a detour, you return
to the “main” route and continue the trip. Control continues as main()
calls other functions.
Introduction to Programming in C ++
Lets have a simple example:
void func1(); prototype of function definition
void main()
{ no return type as it is void in the definition.
---------------
func1(); function call (notice the semicolon)
---------------
}
Return type is void
void func1() no semicolon. Decelerator
{
-------------- function body definition
--------------
} no semicolon.
Lets have another very simple function example:
#include<iostream.h>
#include<conio.h>
void starLine(); //prototype of the function with a name starLine
int main()
{
starLine(); //Calling the function with a name starLine
cout<< “Data type Range” << endl;
starLine();
cout<< “char -128 to 127” <<endl
<< “short -32,768 to 32,767” <<endl
<< “ int system dependent” <<endl
<< “long -2,147,483,648 to 2,147,483,647” << endl;
starLine();
return 0;
}
void starLine()
{
for(int j=0;j<45;j++) definition of the function
with a
cout<< “*”; name starLine
cout<<endl;
}
Introduction to Programming in C ++
Given the next program, which function is the calling function and
which is the called function?
#include<iostream.h>
#include<conio.h>
void nextMsg()
int main()
{
cout<< “Hello!\n”;
nextMsg();
return 0;
}
void nextMsg()
{
cout<< “GoodBye!\n”;
return;
}
3.3 Function Parameters and arguments
The parameters of a function are list of variables used by the function
to perform its task and the arguments passed to the function during
calling of a function are values sent to the function.
The arguments of function calling can be using either of the two
supported styles in C++: passing by value or passing by reference.
Passing by value:
o A value parameter receives a copy of only the value of the
argument passed to it. As a result, if the function makes any
changes to the parameters, this will not affect the argument. For
instance:
#.....
void Foo(int num)
{ Num = 0;
cout<< “num = ” << num << “ \n”;
}
int main(void)
{ int x = 10;
Foo(x);
cout<< “x = ”<<x<< “\n”;
getch();
return 0;
}
o The single parameter of Foo is a value parameter. As far as this
function is concerned, num behaves just like a local variable inside
Introduction to Programming in C ++
the function. When the function is called and x passed to it, num
receives a copy of the value of x. As a result, although num is set to
0 by the function, this does not affect x. the program produces the
following output:
Num = 0
x = 10
o Passing arguments in this way, where the function creates copies of
the arguments passed to it is called passing by value.
Passing by Reference:
o A reference parameter, on the other hand, receives the argument
passed to it and works on it directly. Any change made by the
function to a reference parameter is in effect directly applied to the
argument.
o Passing parameters in this way is called pass-by-reference.
o Taking the same example above:
#.....
#.....
void Foo(int & num)
{
num = 0;
cout<< “num = ” << num << “ \n”;
}
int main(void)
{
int x = 10;
Foo(x);
cout<< “x = ”<<x<< “\n”;
getch();
return 0;
}
o The parameter of Foo is a reference parameter. Num will
correspond to x for this specific program as it x is sent by its
reference and not its value. Any change made on num will be
effected to x. Thus, the program produces the following output:
num = 0
x=0
o Suppose you have pairs of numbers in your program and you want
to be sure that the smaller one always precedes the larger one. To
do this, you call a function, order(), which checks two numbers
Introduction to Programming in C ++
passed to it by reference and swaps the originals if the first is larger
than the second.
#.......
#.......
void order(int &, int &);
int main()
{
int n1 = 99, n2=11;
int n3 = 22, n4=88;
order(n1,n2);
order(n3,n4);
cout<< “n1=”<<n1<<endl;
cout<< “n2=”<<n2<<endl;
cout<< “n3=”<<n3<<endl;
cout<< “n4=”<<n4<<endl;
return 0;
}
void order(int & num1,int & num2)
{
if(num1 > num2)
{
int temp=num1;
num1 = num2;
num2 = temp;
}
}
o In main() there are two pairs of numbers-the first pair is not
ordered and the second pair is ordered. The order() function is
called once for each pair, and then all the numbers are printed out.
The output revels that the first pair has been swapped while the
second pair has not. Here it is:
N1 = 11
N2 = 99
N3 = 22
N4 = 88
o In the order() function the first variable is called num1 and the
second is num2. If num1 is greater than num2, the function stores
num1 in temp, puts num2 in num1, and finally puts temp back in
num2.
6
Introduction to Programming in C ++
o Using reference arguments in this way is a sort of remote control
operation. The calling program tells the function what variables in
the calling program to operate on, and the function modifies these
variables without ever knowing their real names.
4.4 Global versus local variables
Everything defined at the program scope level (outside functions) is
said to have a global scope, meaning that the entire program knows each
variable and has the capability to change any of them.
Eg.
int year = 1994;//global variable
int max(int,int);//gloabal funcrion
int main(void)
{
//…
}
Global variables are visible (“known”) from their point of definition
down to the end of the program.
Each block in a program defines a local scope. Thus the body of a
function represents a local scope. The parameters of a function have
the same scope as the function body.
Variables defined within a local scope are visible to that scope only.
Hence, a variable need only be unique within its own scope. Local
scopes may be nested, in which case the inner scope overrides the
outer scopes. Eg:
int xyz;//xyz is global
void Foo(int xyz)//xyz is local to the body of Foo
{
if(xyz > 0)
{
Double xyz;//xyz is local to this block
…
}
}
Scope Operator
Because a local scope overrides the global scope, having a local
variable with the same name as a global variable makes the latter
inaccessible to the local scope.
7
Introduction to Programming in C ++
Eg
int num1;
void fun1(int num1)
{
//…
}
The global num1 is inaccessible inside fun1(), because it is overridden
by the local num1 parameter.
This problem is overcome using the scope operator ‘::’ which takes a
global entity as argument.
int num1 = 2;
void fun1(int num1)
{
//…
num1=33;
cout<<num1; // the out put will be 33
cout<<::num1; //the out put will be 2 which is the global
if(::num1 != 0)//refers to global num1
//…
}
Automatic versus static variables
The terms automatic and static describe what happens to local
variables when a function returns to the calling procedure. By default,
all local variables are automatic, meaning that they are erased when
their function ends. You can designate a variable as automatic by
prefixing its definition with the term auto.
Eg. The two statements after main()’s opening brace declared
automatic local variables:
main()
{
int i;
auto float x;
…
}
The opposite of an automatic is a static variable. All global variables
are static and, as mentioned, all static variables retain their values.
Therefore, if a local variable is static, it too retains its value when its
function ends-in case this function is called a second time.
To declare a variable as static, place the static keyword in front of the
variable when you define it. The following code section defines three
variables i, j, k. the variable i is automatic, but j and k are static.
Introduction to Programming in C ++
Static variables can be declared and initialized within the function, but
the initialization will be executed only once during the first call.
If static variables are not declared explicitly, they will be declared to 0
automatically.
Eg. void my_fun()
{
static int num;
static int count = 2;
count=count*5;
num=num+4;
}
In the above example:
o During the first call of the function my_fun(), the static variable count will be
initialized to 2 and will be multiplied by 5 at line three to have the value 10.
During the second call of the same function count will have 10 and will be
multiplied by 5.
o During the first call of the function my_fun(), the static variable num will be
initialized to 0 (as it is not explicitly initialized) and 4 will be added to it at line
four to have the value 4. During the second call of the same function num will
have 4 and 4 will be add to it again.
N.B. if local variables are static, their values remain in case the
function is called again.
Inline functions
Suppose that a program frequently requires finding the absolute value
of an integer quantity. For a value denoted by n, this may be expressed
as:
(n > 0 ? n : -n)
However, instead of replicating this expression in many places in the
program, it is better to define it as a function:
int Abs(int n)
{
return n > 0 ? n : -n;
}
The function version has a number of advantages.
It leads to a more readable program.
It is reusable.
The disadvantage of the function version, however is that
Its frequent use can lead to considerable performance
penalty due to overheads associated with calling a function.
The overhead can be avoided by defining Abs as an inline function.
inline int Abs(int n)
Introduction to Programming in C ++
{
Return n > 0 ? n : -n;
}
The effect of this is that when Abs is called, the compiler, instead of
generating code to call Abs, expands the program body and substitutes
the body of Abs in place of the call. While essentially the same
computation is performed, no function call is involved and hence no
stack frame is allocated.
The "inline" keyword is merely a hint to the compiler or development
environment.
Not every function can be inlined. Some typical reasons why inlining
is sometimes not done include:
the function calls itself, that is, is recursive
the function contains loops such as for(;;) or while()
the function size is too large
Another good reason to inline is that you can sometimes speed up
your program by inlining the right function. Instead of calling the
function every time it is invoked, the compiler will replace the function
call with a copy of the function body. If it's a small function which gets
called a lot, this can sometimes speed things up.
Most of the advantage of inline functions comes from avoiding the
overhead of calling an actual function. Such overhead includes saving
registers, setting up stack frames, and so on. But with large functions
the overhead becomes less important.
Concerning inline functions, the compiler is free to decide whether a
function qualifies to be an inline function. If the inline function is
found to have larger chunk (amount) of code, it will not be treated as
an inline function, but as like other normal functions.
Then, Why not inline everything? :Since the compiler will copy the
entire function body every time the function is called, if it is a large
function (more than three or four lines), inlining can increase the size
of your executable program significantly.
4.5 Default arguments and function overloading
C++ has two capabilities that regular C doesn’t have. Default
arguments and function overloading.
Default arguments
Default argument is a programming convenience which removes
the burden of having to specify argument values for all function
parameters.
10
Introduction to Programming in C ++
Eg. You might pass a function an error message that is stored in a
character array, and the function displays the error for a certain
period of time. The prototype for such a function can be this:
Void pr_msg(char note[]);
Therefore, to request that pr_msg() display the line ‘Turn printer
on’, you call it this way:
Pr_msg(“Turn printer on”);
As you write more of the program, you begin to realize that you
are displaying one message-for instance, the ‘Turn printer on’ msg-
more often than any other message.
Instead of calling the function over and over, typing the same
message each time, you can set up the prototype for pr_msg() so
that it defaults to the ‘turn printer on’ message in this way:
Void pr_msg(char note[] = “Turn printr on”);
This makes your programming job easier. Because you would
usually want pr_msg() to display ‘turn printer on’, the default
argument list takes care of the message and you don’t have to pass
the message when you call the function.
For functions having more than one argument with default, the
parameters with possible default value should be declared in the
right side of the function definition and prototype.
E.g.: Let us develop part of the program with default arguments.
#include…..
void Add_Display(int x=10, int y=20, int z=30)
{
cout<< (x+y+z);
}
void Mult_Dispaly (int x, int y=70)
{
cout<< (x*y);
}
void main()
{
int a=40, b=50, c=60;
Add_Display(a,b,c); //will print 150 (ie 40+50+60)
Add_Display(a,b); //will print 120 (ie 40+50+30)
Add_Display(a); //will print 90 (ie 40+20+30)
Add_Display(); //will print 60 (ie 10+20+30)
Mult_Display(a,b) //will print 2000 (40*50)
Mult_Display(a) //will print 2800 (40*70)
//Mult_Display() //is invalid as there is no default for x
getch();
11
Introduction to Programming in C ++
}
//the following function definition is invalid as z is
//a parameter without a default and written after y
//parameters with default should always be at the
//right side of function declaration
void Mult_Dispaly (int x, int y=70, int z)
{
cout<< (x*y*z);
}
//thus the following function definition will be correct
void Mult_Dispaly (int x, int z, int y=70)
{
cout<< (x*y*z);
}
Overloaded Functions
Unlike C, C++ lets you have more than one function with the same
name. In other words, you can have three functions called abs() in
the same program.
Functions with the same name are called overloaded functions.
C++ requires that each overloaded functions differ in its argument
list. Overloaded functions enable you to have similar functions that
work on different types of data.
Suppose that you wrote a function that returned the absolute value
of what ever number you passed to it:
int iabs(int i)
{ if(i<0)
Return (i*-1);
else
Return (i);
}
float fabs(float x)
{ if(x<0.0)
Return (x * -1.0);
else
Return (x);
}
Without using overloading, you have to call the function as:
int ans = iabs(weight);//for int arguments
float ans = fabs(weight);//for float arguments
But with overloading, the above code can be used as:
12
Introduction to Programming in C ++
int abs(int i);
float abs(float x);
int main()
{
…
ians = abs(i);//calling abs with int arguments
fans = abs(p);//calling abs with float arguments
…
}
int abs(int i)
{
if(i<0)
Return i*-1;
else
Return I;
}
float abs(flaot x)
{
if(x<0.0)
Return x*-1.0;
else
Return x;
}
N.B: if two or more functions differ only in their return types, C++
can’t overload them. Two or more functions that differ only in their
return types must have different names and can’t be overloaded
4.6 Recursion
A function which calls itself is said to be recursive. Recursion is a
general programming technique applicable to problems which can be
defined interms of themselves. Take the factorial problem, for instance
which is defined as:
- factorial of 0 is 1
- factorial of a positive number n is n time the factorial of n-
1.
The second line clearly indicates that factorial is defined in terms of
itself and hence can be expressed as a recursive function.
int Factorial(unsigned int n )
{
return n = = 0 ? 1 : n * factrial(n-1);
}
For n set to 4, the following figure shows the recursive call:
Introduction to Programming in C ++
Factorial(4)
24
4 * Factorial(3)
6 3 * Factorial(2)
2 2* Factorial(1)
1 1
The stack frames for these calls appear sequentially on the runtime
stack, one after the other.
A recursive function must have at least one termination condition
which can be satisfied. Otherwise, the function will call itself
indefinitely until the runtime stack overflows.
The three necessary components in a recursive method are:
1. A test to stop or continue the recursion
2. An end case that terminates the recursion
3. A recursive call(s) that continues the recursion
let us implement two more mathematical functions using recursion
e.g the following function computes the sum of the first N positive
integers 1,2,…,N. Notice how the function includes the three necessary
components of a recursive method.
int sum(int N)
{
if(N==1)
return 1;
else
return N+sum(N);
}
The last method computes the exponentiation An where A is a real
number and N is a positive integer. This time, we have to pass two
arguments. A and N. the value of A will not change in the calls, but the
value of N is decremented after each recursive call.
float expo(float A, int N)
{
if(N==1)
return A;
else
return A * expo(A,N-1);
}
14
Introduction to Programming in C ++
Try to use a recursive function call to solve the Fibonacci series.
The Fibonacci series is :
0,1,1,2,3,5,8,13,21,…
the recursive definition of the Fibonacci series is as
follows: Fibonacci (0) =0
Fibonacci (1) =1
Fibonacci (n) =Fibonacci (n-1) +Fibonacci (n-2);
Recursion versus iteration
Both iteration and recursion are based on control structure.
Iteration uses a repetition structure (such as for, while, do…
while) and
recursive uses a selection structure (if, if else or switch).
Both iteration and recursive can execute infinitely-an infinite
loop occurs with iteration if the loop continuation test become
false and infinite recursion occurs id the recursion step doesn’t
reduce the problem in a manner that coverage on a base case.
Recursion has disadvantage as well. It repeatedly invokes
the mechanism, and consequently the overhead of method calls.
This can be costly in both processor time and memory space. Each
recursive call creates another copy of the method (actually,
only the function’s variables); this consumes considerable memory.
N.B: Use recursion if:
1. A recursive solution is natural and easy to understand
2. A recursive solution doesn’t result in excessive
duplicate computation.
3. the equivalent iterative solution is too complex and
4. of course, when you are asked to use one in the exam!!