Functions

SPA4321
Introduction to C++
2015-16
Functions
In this document you’ll learn about how to use functions to wrap up sets of instructions and
parameterise them so they can be used in more than one location in you program.
Function Basics
Functions are collections of instructions that you can write once, and then use elsewhere in your
program. Here is an example of a simple function to add two numbers together:
In some simple cases a function can be thought of as being a little like a formula in maths – we often
even use the same language:
𝑓(𝑎, 𝑏) = 𝑎 + 𝑏
Is a function of a and b that evaluates to the sum of the two parameters.
A function is comprised of four parts: the return type, the name, the parameter list, and the body.
Return type:
The return type lets the compiler know what the type of the result of calling the function is going to
be. This should be a valid type or the keyword void if you don’t want to get any result from calling
the function.
In this case the return type is float. That means that somewhere in the function must be a return
statement with a value, and the value must have type float (or something that converts to a float).
1
SPA4321
Introduction to C++
2015-16
Function Name:
Every function should have name. This name is how you refer to the function elsewhere in your code
– in a similar way to defining a new variable. The name of this function is myFunc.
Function parameters:
The parameter list is contained inside the brackets and consists of a comma separated list of typename pairs. Each parameter is listed first with its type and then its name. The name that you put
here is only defined within the function and is what you use to refer to the parameter within the
function body.
The function parameters are defined as if they were in the scope of the function – that is – they are
local to the function scope, can’t be seen outside of it and will disappear once the function reaches
the end.
In this case there are two parameters – both have type float. The first is called parameter1 and the
second is called parameter2.
Function Body:
Following this you see the body of the function – enclosed in a scope. The function body consists of
the instructions that belong to the function – the actions that should be carried out when the
function is executed.
This example contains two instructions – the first takes the two function parameters, adds them
together and stored the result in a new variable called x, with type float. The second instruction
indicates what to return as the value of the function, in this case, the contents of x. The return
keyword is used to indicate to the compiler what the result of the function should be.
In principle all functions that have a return type other than void need a return statement. In practise
the compiler will let you get away with forgetting the return statement and just give you a warning.
But in general your code won’t work properly. This is quite a common mistake so it is important to
always check for warnings in CLion.
Function signature:
The function name plus the list of parameters and their types define what is called the signature of
the function (note the return type is not part of the signature). When you call a function, when you
try to run through its instructions, the compiler figures out which function you meant by comparing
the signature used in the call with the list of functions it knows about and calls the one that matches
the best. In C++ you can define functions with the same name – so long as the signature is different.
This will be covered in more detail later in the course.
2
SPA4321
Introduction to C++
2015-16
Calling a function: Execution or Invocation
To execute a function – that is to run the instructions inside it - you need use its name together with
brackets as follows:
Here two floats are created, a and b, and initialised with values 10 and 20 respectively. Then in the
third line the function is called, passing the values of a and b as parameters. The execution of the
program then jumps to the function and runs through the instructions in the function until either it
hits the curly bracket at the end of the function scope – or it reaches a return statement. At which
point the flow passes back to the original code and continues on line-by-line in the usual way.
In this example, the value returned by the function is stored in a new variable, value.
Function Parameters
An important feature of functions is that the parameters – also called arguments – are passed-byvalue. What that means is that the variables inside the function get a copy of the value that the
function was called with – they are not attached in any way to the original variables. In the example
above parameter1 is a copy of a, so changes made to parameter1 inside the function have no
effect on a whatsoever, likewise for parameter2.
The parameters are matched up purely by the order in which they appear in the function call and
function definition – the names don’t have to match up between the definition and the function call.
Pass-by-value is an important feature as it allows you to limit the side-effects of the operation of the
function – it can’t modify the original variables that are passed as parameters, only the copies that
are made. This can dramatically simplify debugging a broken program and save a lot of time.
Default Arguments
When you define your function, you can also provide default values for the arguments:
In this slight modification of the previous example, a default value has been added for the second
argument. What this means, is that if you call this function but only provide one parameter, its value
will be copied to parameter1 and parameter2 will be set to 0. Because C++ uses the ordering of
the parameters to match up with the calling arguments once you provide a default argument for one
parameter you must provide default values for all the parameters that come after it in the list. For
example the following code is illegal:
3
SPA4321
Introduction to C++
2015-16
But this would be fine:
One final note on this topic: if you have split your function into a declaration and a definition as
described below – and this is almost always what you will want to do – then you need to put the
default arguments in the declaration and do not put them in the definition.
Return values
Just as the parameters are passed by value, ie are copied, so too is the return value. This is
important to remember since in this example, the variable x is local to the function scope – just like
any other scope. That means that once the flow of the program reaches the end of the function
scope the variable is destroyed. This will be particularly important when we look at a feature of C++
called references.
The return value you pass, must match the return type you specified in the function definition – or at
least have an implicit conversion to that type. Likewise, when assigning the return value to
something:
The type needs to match the return type (or an implicit conversion between the types must exist), or
your code won’t compile.
You might have noticed already that you get warnings from the compiler when using some of the
maths functions and storing the result in a float – since most of the maths functions return values
with type double.
In this case storing the result in an integer will work – because a conversion exists from a float to an
integer (though it might not be what you want), but storing it in a string won’t work, because there
is no conversion float to string.
One final thing to note is that you are not obliged to use the return value of your function. You can
happily just write code like:
This will execute the function, and throw away the return value. It isn’t very useful in this case, but in
some instances the function might have side effects beyond simply returning a value.
4
SPA4321
Introduction to C++
2015-16
If you don’t want your function to return a value you can declare so with a special keyword: void
This function outputs the parameter to the console. It doesn’t really need a return value, so you can
put void as the return type to indicate it doesn’t return anything.
Declaring and Defining a function
Before you can use a function in a source code file, the compiler has to already know what the name
of the function means before it gets to the line where you call it. One way to do this is just to define
the function before your main function:
The bit where you list the actual instructions that belong to the function is called the definition.
If you put it after int main in the file – it won’t work – the name myfunc has to be defined before the
compiler gets to the line where you use it.
Also, note, you are not allowed to define functions inside of other functions. All functions must be
defined outside any other block of code- though they can be defined inside a namespace.
Now for various reasons you might not want to put the function in front of int main, maybe you
want it in a different file. In this case you mustn’t define it again in your main.cpp – since C++ only
allows you to define a function once. So instead to tell the compiler what the name means – without
defining the full set of instructions – you need a declaration. A declaration looks like the first line of
the function definition – missing the curly brackets and with a semi-colon:
5
SPA4321
Introduction to C++
2015-16
The first line of the previous example shows the function declaration. I’ve moved the function
definition to the end. This version will work – if you remove the declaration it will break – even
though the definition is in the same file.
You can declare the function as many times as you like – but you can only define it once per
program.
You needn’t put it at the end of main.cpp, you could put things in different files.
In this example, the main function stays in main.cpp, but the function definition has been moved to
myfunc.cpp and the function declaration is now in a header file myfunc.hpp. Then to make sure the
compiler sees the function declaration when it compiles main.cpp a line is added - #include
“myfunc.hpp”.
Note, in this case double quotes are used instead of < >. This tells the compiler that this is a user
header file rather than a system header file. The difference between the two is just in the order in
which the compiler looks into different folders to find the header file – in the case of < > it looks in
system folders first, then user folders. In the case of “ “ it looks in the user folders first, and then the
system folders. In each case it uses the first file it finds that matches the given filename. For this
course, it won’t make a great deal of difference but it is important to be aware of this and get used
to following the convention.
main.cpp
myfunc.hpp
myfunc.cpp
6
SPA4321
Introduction to C++
2015-16
Another thing you should notice is the use of include guards in the header file. The three lines
beginning with # in myfunc.hpp indicate some instruction to the pre-processor that we discussed in
the C++Introduction.
The first line actually comes as a pair of lines:
and
This basically tells the pre-processor to only include the lines between these two statements if the
symbol: MYFUNC_HPP_ has not already been defined.
The second line:
Defines the symbol MYFUNC_HPP_, it doesn’t give it any particular value – just creates it. Thus this
file can only be #included once. This gets important when you have header files that do more than
just declarations where including it twice might have other side-effects. This is particularly important
when you have header files including other header files – you could end up accidentally including
one twice or even set up an infinite loop of inclusions! A very common mistake is to forget these
header guards, luckily if you create the file with Clion as a header file, it will automatically create
them for you.
In this example, the definition of myfunc has been moved to another file – this might be useful if
you wanted to use the file in another project as well. Furthermore, this highlights the fact that the
compiler doesn’t need to see the function definition to compile main.cpp. So long as it has the
declaration, you have basically promised that the definition will exist somewhere, and will get
compiled in another file (or exist already in a library). The eventual connection of the name to the
actual set of instructions will be handled by the linker in the last step of the build process when it
constructs the program. If the definition of the function isn’t found in another object file or in any of
the libraries – the build will fail with an unresolved symbol error.
7
SPA4321
Introduction to C++
2015-16
Exercises
These exercises are not assessed but completing them will help you get to grips with functions.
Exercise 1 : Functions1





Create a new project called Functions1
Commit and push your project to GitLab
Write a new function in main.cpp:
o Return type: float
o Function name: add
o Parameters: two floating point numbers, a and b
o Function body:
 Your function should add together the two parameters a and b and return
the result. (ie use the return statement)
Now in your main function write the following code:
o Read two floating point numbers from the console and store them in two variables
called x and y.
o Call your function with x and y as the parameters and store the return value (ie the
result) in another floating point variable called z
o Print z to the console
Commit and push your code to GitLab
8
SPA4321
Introduction to C++
2015-16
Exercise 2 : Functions2


Create a new project called Functions2
Create a new source code file called functions.cpp
o You can do this by right-clicking on your project and selecting “New” and then “New
C/C++ Source file”
o You should see a window like this pop-up
o

Make sure the “Create associated header” and “Add to targets” boxes are ticked,
then click OK.
o It will then ask if you want to add the file to Git – click yes. Though if you click No
you can add the files in the usual way by right-clicking on the project and selecting
Git->Add
You should now have two new files in your project: functions.hpp and functions.cpp
o In functions.cpp write the definition (ie the bit that contains the function
instructions) for a function that does the following:
 Return type: void
 Name: fizzBuzz
 Parameters: one integer called number
 Function body:
 Print the parameter to the console
 If the parameter is divisible by 3 print the word “fizz” to the console
– one the same line as the number
 If the parameter is divisible by 5 print the word “buzz” to the
console – on the same line as the number
 If the parameter is divisible by 3 and 5 print “fizz buzz” to the
console – on the same line as the number
 This function has return type void so it doesn’t need a return statement
o In main.cpp write code to do the following:
 Add in the appropriate place #include “functions.h”
 In the main function write code to do the following:
 Using a for loop, loop over the integers from 1 to 50 and for each
integer call your function with the number as the parameter.
9