程序代写案例-FIT1048

欢迎使用51辅导,51作业君孵化低价透明的学长辅导平台,服务保持优质,平均费用压低50%以上! 51fudao.top

i
FIT1048 - Foundations of C++
Matthew Butler
ii

FIT1048 - Foundations of C++
Matthew Butler
Version: 2015v0.1
Gen
erated by Alexandria (https://www.alexandriarepository.org) on July 11, 2016 at 4:20 pm AEST
14 A Wrap Up Of Our C++ Journey
iii
Contents
Title i .............................................................................................................................................
Copyright ii ...................................................................................................................................
1 An Introduction to C++ 1 .......................................................................................................
1.1 A Brief History of C++ 2 ...............................................................................................
1.2 Why C++? 3 ....................................................................................................................
1.3 What Are We Covering In This Unit? 4 .......................................................................
1.4 The Obligatory Hello World 5 ......................................................................................
1.5 Dissecting our Hello World Program 6 ......................................................................
1.6 An Brief Introduction to Object Orientation 8 ..........................................................
1.7 The Standard Template Library (STL) 9 ....................................................................
1.8 Introduction to C++ Summary 10 ...............................................................................
2 C++ Syntax Building Blocks 1: Sequence, Data Types, and I/O 11 .................................
2.1 The Sequence Control Structure 12 ...........................................................................
2.2 An Introduction to Data Types 13 ...............................................................................
2.3 Data Types in C++ 14 ...................................................................................................
2.4 Declaring Variables 15 .................................................................................................
2.5 Constants in C++ 17 .....................................................................................................
2.6 Working with Variables 18 ...........................................................................................
2.7 Casting 19 .......................................................................................................................
2.8 Working with Basic Classes and Objects 20 .............................................................
2.9 Variable Scope 21 .........................................................................................................
2.10 Data Output to Screen 22 ..........................................................................................
2.11 Data Input from the Keyboard 23 ............................................................................
2.12 File Input/Output in C++ 24 ......................................................................................
2.13 Namespaces 26 ............................................................................................................
2.14 Syntax Building Blocks 1 Summary 27 ....................................................................
3 Coding Conventions and Style 28 .........................................................................................
3.1 The Need For Consistency! 29 ....................................................................................
3.2 Naming Conventions 30 ...............................................................................................
3.3 Commenting 31 ..............................................................................................................
3.4 Indenting and Whitespace 32 .....................................................................................
3.5 Coding Conventions Summary 33 ...............................................................................
4 C++ Syntax Building Blocks 2: Selection and Repetition 34 ............................................
4.1 The Selection Control Structure 35 ............................................................................
4.2 Expressions 37 ...............................................................................................................
4.3 Selection in C++ 39 ......................................................................................................
4.4 The Repetition Control Structure 41 ..........................................................................
4.5 Loops in C++ 43 ............................................................................................................
4.6 How to Choose a Loop? 45 ...........................................................................................
4.7 Syntax Building Blocks 2 Summary 46 ......................................................................
5 Arrays and Vectors 47 ............................................................................................................
5.1 Introduction to Arrays 48 .............................................................................................
5.2 One Dimensional Arrays in C++ 49 ............................................................................
5.3 Two Dimensional Arrays 51 .........................................................................................
5.4 2D Arrays in C++ 52 .....................................................................................................
14 A Wrap Up Of Our C++ Journey
iv
5.5 Problem Solving with Arrays 55 ..................................................................................
5.6 Vectors and the STL 57 ................................................................................................
5.7 Using Vectors 58 ...........................................................................................................
5.8 Iterators and STL Algorithms 60 .................................................................................
5.9 Arrays and Vectors Summary 63 ................................................................................
6 Functions 64 .............................................................................................................................
6.1 The Purpose of Functions 65 .......................................................................................
6.2 Functions in C++ 66 ......................................................................................................
6.3 Calling Functions 68 .....................................................................................................
6.4 Passing Data to Functions 69 ......................................................................................
6.5 Returning Data from Functions 71 .............................................................................
6.6 Overloading Functions 73 ............................................................................................
6.7 Variable Scope Revisited 75 ........................................................................................
6.8 Header Files in C++ 77 .................................................................................................
6.9 Functions Summary 79 .................................................................................................
7 Introducing Object Oriented Programming 80 ...................................................................
7.1 Object Oriented Design 81 ...........................................................................................
7.2 Classes and Objects 83 .................................................................................................
7.3 Deconstruction of a Class 84 .......................................................................................
7.4 Object Oriented Programming Summary 85 .............................................................
8 Writing Our Own C++ Classes 86 ..........................................................................................
8.1 Basic Class Structure in C++ 87 .................................................................................
8.2 Using our Classes to create Objects in C++ 88 ........................................................
8.3 Data Members 89 ..........................................................................................................
8.4 Member Functions 91 ...................................................................................................
8.5 Static Members 92 ........................................................................................................
8.6 C++ Header Files Revisited 93 ...................................................................................
8.7 Constuctors 95 ...............................................................................................................
8.8 Writing Multiple Constructors 96 ...............................................................................
8.9 Destructors 97 ...............................................................................................................
8.10 Writing Your Own Classes Summary 98 ..................................................................
9 Multi-Class Program Design 99 .............................................................................................
9.1 Creating Programs With Two or More Independent Classes 100 ..........................
9.2 Creating Programs With Interrelated Classes 102 ..................................................
9.3 Troubleshooting Your Classes 104 .............................................................................
9.4 Multi-Class Program Summary 105 ............................................................................
10 Pointers 106 ...........................................................................................................................
10.1 An Introduction to References 107 ..........................................................................
10.2 Using References 108 .................................................................................................
10.3 Constant References and Returning References 109 ............................................
10.4 An Introduction to Pointers 110 ...............................................................................
10.5 Pointer Basics 111 .......................................................................................................
10.6 Constant Pointers 113 ................................................................................................
10.7 Pointers to Objects 114 ..............................................................................................
10.8 Passing and Returning Pointers 115 ........................................................................
10.9 Pointers or References? 116 .....................................................................................
10.10 The Heap and The Stack 117 ...................................................................................
10.11 The New Keyword 118 ..............................................................................................
10.12 Cleaning Up Memory 120 .........................................................................................
14 A Wrap Up Of Our C++ Journey
v
10.13 Practical Use of Pointers 122 ..................................................................................
10.14 Pointers Summary 124 .............................................................................................
11 Inheritance 125 ......................................................................................................................
11.1 What is Inheritance? 126 ...........................................................................................
11.2 Inheritance in C++ 127 ..............................................................................................
11.3 What Happens When We Create Child Objects? 129 .............................................
11.4 Function Overriding 130 ............................................................................................
11.5 Multiple Inheritance 132 ............................................................................................
11.6 Inheritance Summary 133 ..........................................................................................
12 Polymorphism 134 .................................................................................................................
12.1 Revisiting Inheritance and Pointers 135 .................................................................
12.2 Pointers to Base Classes 136 ....................................................................................
12.3 Virtual Functions 137 .................................................................................................
12.4 Virtual Destructors 138 ..............................................................................................
12.5 Static Casting 139 .......................................................................................................
12.6 Polymorphism Summary 140 .....................................................................................
13 Object Oriented Design 141 .................................................................................................
13.1 Thinking About Object Oriented Design 142 ..........................................................
13.2 Separating Presentation From Logic 143 ................................................................
13.3 Abstract Classes 144 ..................................................................................................
13.4 What Are Design Patterns? 145 ................................................................................
13.5 Singletons 146 .............................................................................................................
13.6 Factories 148 ...............................................................................................................
13.7 Object Oriented Design Summary 150 ....................................................................
14 A Wrap Up Of Our C++ Journey 151 ...................................................................................
i
1 An Introduction to C++
1

1
An Introduction to C++
Welcome!
In this Learning Module we will introduce you to C++. Don't worry… we don't assume you have done any
programming before! But here we will run through a bit of the history of C++ along with showing you
your first C++ program.
The Learning Objectives for this module are:
Become familiar with the background of C++ and it's importance in computer programming and
systems development
Become familiar with the form of a basic C++ program
1.1 A Brief History of C++
2

1.1
A Brief History of C++
In the late 1970's, Bjarne Stroustrup began working on a programming language derived from C, which he
called "C With Classes". The idea was to create a language that was powerful enough for large software
development, but also faster than other languages. His idea was to add elements like classes and strong
typing to the C language.
In 1983, his language officially became C++, and in 1985 he released the first edition of his book "The
C++ Programming Language (http://www.stroustrup.com/4th.html)". C++ was now being spread to programmers
the world over!
Over the past decades, C++ has evolved, with C++11 being the latest release in 2011. More releases are
planned for the near future.
1.2 Why C++?
3

1.2
Why C++?
So why learn C++? Why should I choose to study it over many other languages? Good question!
C++ is one of the main programming languages in use today. It is acknowledged as one of the most
versatile and is seen as a direct precursor to other languages such as Java and C#. C++ is also versatile
in that it can be implemented on a wide variety of hardware and operating systems. C++ also blends high
and low level elements to it, meaning that you don't have to understand the complexities of your
computer, but can implement powerful low level functions.
Compared with Java or C# we lose some features like memory management and garbage collection,
however we gain a lot more power. For example:
C++ is compiled down to machine code
Have direct access to hardware
Code can be non OO if needed
Can directly modify memory
Performance can be dramatically improved
C++ has dominated Game Development for the same reasons. It's fast (you can even go down to
assembly if required), it's flexible (you can use different paradigms) and it's well supported (graphics,
physics, audio engines widely available).
All of this makes your decision to study C++ an excellent one!
1.3 What Are We Covering In This Unit?
4

1.3
What Are We Covering In This Unit?
In this unit you will be introduced to the fundamentals of the C++ programming language. It is expected
that you have covered the basics of programming before, although it doesn't have to have been with a
syntactic programming language… we just need you familiar with the basic control structures like loops
and decisions, and be able to consider how a problem may be solved through programming.
So this unit can be broken up quite nicely into three main areas:
Programming Fundamentals using the C++ language… variables, loops, decisions, coding good1.
practice and the like.
Object Oriented Programming using C++… becoming familiar with OO, how we solve problems2.
using this design paradigm, and how we implement OO programs with C++.
C++ Specifics… features of C++ that are particular to C++ , such as the Standard Template3.
Library and Pointers.
The unit Syllabus shows you all of the individual topics we are going to cover. We have plenty to get
through!
1.4 The Obligatory Hello World
5

1.4
The Obligatory Hello World
Here is a "Hello, World!" program to introduce you to C++. Don't worry… we will dissect it in the next
module. But see if you can guess what the purpose of each line of code might be (including the curly
brackets!).
// This is my "Hello, World!" program
#include
int main()
{
std::cout << "Hello, world!\n";
}
1.5 Dissecting our Hello World Program
6

1.5
Dissecting our Hello World Program
Here's our "Hello, World!" program again…
// This is my "Hello, World!" program
#include
int main()
{
std::cout << "Hello, world!\n";
}
Could you work out what each line does? Let's start at the beginning.
Line 1: This is a comment. The line doesn't do anything computationally, but is important in telling us
what the code is going to do. The "\\" at the start of the line turns it into a comment, meaning the line
won't do anything.
Line 2: The "#" at the start of the line means this will be interpreted before the compiler looks at the rest
of the code. This is important, as we are telling it to include the "" section of code which lets
us perform input and output.
Line 3: This is blank which is fine to do in C++! It adds to the readability of the code.
Line 4: Here we are designating a block of code and calling it "main". We will discuss functions in more
detail later on. But it is important to note that the function called main is important as it is the function
called when the program is run. The execution of all C++ programs begins with the main function.
Lines 5 and 7: These curly brackets signify the start and end of the function called "main". Everything in
between runs when we call the main function.
Line 6: The trickiest line! As you may have guessed, this line will display the text "Hello, world!" to the
screen (without the " " marks). "std::cout" identifies that we are going to be outputting something (to the
screen). The "<<" says to send what follows to the output device. Next, the thing in the quotation marks
is what we want to print to screen. Finally, we need a semicolon to indicate that the line of code is
finished!
But what about the "\n" you ask? That is a special code that means to start a new line. So if we were to
write something else to the screen, it would start on a new line.
Question: What line/s would you change to write something different to the screen?
1.5 Dissecting our Hello World Program
7
1.6 An Brief Introduction to Object Orientation
8

1.6
An Brief Introduction to Object Orientation
C++ is considered an object-oriented language. By object-oriented we are talking about a particular
paradigm of programming. A paradigm is a philosophy of how we approach primarily the program design
process. For example, we might be:
Object-Oriented
Procedural
Event driven
Functional
With the OO paradigm, we focus on the creation of "objects" that have both data and things that can be
done with them. Objects are typically instances of "classes". A class is like a template that describe what
all instances will be like in general… for example, what data they have (data members) and what things
can be done to them (member functions). With these classes we can create (theoretically) an infinite
number of instances.
Most importantly, if well designed, we can reuse these classes in other programs. For example, what
might be classes in one of our programs? For each one think about what would be the common data that
is encapsulated by the classes below?
person
student
employee
customer
date
clock
Let's consider the "student" example. What Data Members might it have?
ID
Name
Date of Birth
Email Address
Course being studied
And what about Member Functions?
Change address
Enroll in a unit
With C++ we have to adopt the OO paradigm. However as we have seen with our Hello World example,
we can create basic programs that don't seem like they use classes at all! While we will avoid extensive
use of classes and objects for the first few modules, we will soon start designing good OO solutions!
1.7 The Standard Template Library (STL)
9

1.7
The Standard Template Library (STL)
In a way C++ lacks a lot of useful functionality. The Standard Template Library (STL) is a collection of
programming work that has been done for us. It contains containers, algorithms, iterators and functions
amongst other things.
In fact we have used the STL already with our use of cout!
The STL has evolved with each iteration of C++. We will take the STL for granted in our programming with
C++ and will make more extensive use of it as we progress through the foundations of C++.
1.8 Introduction to C++ Summary
10

1.8
Introduction to C++ Summary
This chapter was designed to provide an introduction to the C++ language, its history, and its
foundations. It is not expected that you can now go away and create complex C++ programs, rather it
will allow you to start experimenting with some basic code.
Please use the comment section in each chapters summary (like this one) to provide any comments here
regarding this chapter… what you liked and what can be improved! It will help us to continually improve
our materials for you.
2 C++ Syntax Building Blocks 1: Sequence, Data Types, and I/O
11

2
C++ Syntax Building Blocks 1: Sequence, Data
Types, and I/O
Now it is time to get started in earnest with C++!
As mentioned in the first chapter, it is not expected that you have much experience with computer
programming. As such, this chapter is all about familiarising you with some basics of programming and
then placing them into the C++ context. This will include how we work with data in our programs, how we
can get things in and out of the computer, and getting some basic program logic working.
The learning objectives for this chapter are:
Understand how to declare and use primitive data types in our programs
Become aware of the different data types we have in C++ and why we may choose particular
types to represent data in our programs
Understand how input/output is achieved in C++ using cin and cout
Understand how simple objects are declared and used in the C++ context
2.1 The Sequence Control Structure
12

2.1
The Sequence Control Structure
The Sequence Control Structure is much like a flow chart diagram. The way that code functions is in an
ordered manner starting at the first line of code and stepping through line-by-line. As code is run, the
code on the first line is the first to run, followed by the second line, third, fourth, etc.
Code will always flow from line to line except under special circumstances like repetition and selection
structures, which we will cover those in later topics. In those times we may skip lines or repeat them, and
at other times we may even branch off to run a different block of code before coming back to where we
left (like with functions).
Below is a basic example that creates 3 integer variables and gives them a number value. It then Creates
a result variable, multiplies the first 2 numbers together and saves that in our result variable, then divides
that previous result variable value by the 3rd number that was created at the start. Note how on the 6th
line we can use the result variable in the calculation because it performs that calculation and then stores
that value in our result in front of the = sign. This is due to Calculations on the right of the equals sign
being performed before the left side. Don't worry about the code too much, it will make more sense as
you work through this chapter!
int main()
{
int firstNum = 4, secondNum = 3, thirdNum = 2;
int result = 0;
result = firstNum * secondNum;
result = result / thirdNum;
}
2.2 An Introduction to Data Types
13

2.2
An Introduction to Data Types
When writing programming code, we will use things called variables to store our data in. Variables can
have different types and will store different data based on the type that is selected. For example,
sometimes we will want to store a whole number, maybe a character, and other times a long decimal
point number.
It is important to select a type when creating variables so the computer will know what kind of data it is
trying to remember and how to store it in the computers memory. Each different type has an implication
on how much of the computers memory it needs to put aside, so it is important to think about.
Say we have a cube that has a certain size. For this example we'll say the size is 5 units (this is an
imaginary cube so the actual units of measure doesn't matter for now). Now if we want the program to
use and remember the size of the cube, we need to store it in a variable. Can we simply say size = 5?
No, because the computer doesn't know what 5 is. Is it a letter, a number, a word? We need to tell the
computer that 5 is in fact a number and it doesn't contain any decimal points. This means in this case we
want to make our variable an integer. In the next section you can view all the types you will learn
(including integers) in this unit and the following section will then show you how to set up a variable like
that to use.
2.3 Data Types in C++
14

2.3
Data Types in C++
In C++, we will be initially focusing on Fundamental Data types but you will learn about all data types by
the end of the unit.
Fundamental Data Types are the simplest to understand and define. They can vary from language to
language, but there are usually the same basic types, such as numbers, characters, and true/false. Below
are the types as represented in C++:
Data type
name Memory Size Range (signed) Comment Example
char 1 Byte -128 to 127
Single characters enclosed in
single quotes. Non printable
escape sequences.
'a', 'Z','@', '\n', '\t',
' '
short Int
(short) 2 Bytes -32768 to 32767
int 4 Bytes -2147483648 to2147483647
Integer numeric value (whole
number). 24
long int (long) 4 Bytes -2147483648 to2147483647
bool 1 Byte false, true This is known as a boolean false, true
float 4 Bytes +/- 3.4e +/- 38 (7sig digits)
Floating point number
(contains fractional part after
decimal point).
51.45458
double 8 Bytes +/- .7e +/- 308(15 sig digits) 751.454581765254
2.4 Declaring Variables
15

2.4
Declaring Variables
Now that you know the different types of data, how do we use them?
We'll go back to our example of a cube that has a size of 5 units. As stated before, we can't simply say
that our cube is of size 5. We know that we need to tell the computer that it is an integer first so it knows
how to store that value. We do this like so:
int size = 5;
We can see above that first we say what datatype we are making this variable. We then name our
variable an appropriate name, (in this case i called it size) and then we set it to the value of 5.
But does the declaration of variables always need to look like this? What if i don't know the size of my
cube yet, but I know that I will when I run the program?
This is when we can simply create the variable like so:
int size;
By typing that line of code, our computer program will still create the variable, it knows that it's an int and
it names the variable "size". While we don't necessarily have to set the initial value, it is still a good idea
to do so, so that we know what value it will start the program with. Choosing an inconsequential value
(often 0) is a good idea.
This is the declaration of a variable. It is the creation part. The beauty of a variable is that later on we can
change its value by simply calling the variable by it's name and assigning it a value because the variable
now exists.
size = 5;
Here, we don't worry what the value of the variable was beforehand. That is discarded and it is set to the
new value. Remember you need to get the correct data type for our variables. We can't simply say:
size = "five";
Because that is a string and our "size" variable is an integer.
When it comes to declaring our variables, we can also declare multiple variables on the same line
provided they are the same type. Do this if it is a logical grouping and you think it will help people read
the code.
int size = 0, weight = 0;
2.4 Declaring Variables
16
Here are some more examples of variables. Note that each has a slightly different way they are assigned
a value, depending on what type of data is being stored.
char letter = 'a';
string name = "Matt";
bool isFinished = false;
double price = 2.99;
2.5 Constants in C++
17

2.5
Constants in C++
Variables in C++ can be declared 'constant'. This means that their value cannot be changed after
declaration. They are important to use if we know the value should not change over the course of the
program.
To do this we use the const keyword when declaring:
const int HOURS_IN_DAY = 24;
This can now never be changed in code. Note the use of all caps in the name of the variable. This is a
naming convention that is often used to provide an easy way to recognise in our code that it is a constant.
2.6 Working with Variables
18

2.6
Working with Variables
As you we have alluded to, a variable can be used just like a regular number/character. As such, you can
perform appropriate operations on them. So for a number variable, you could perform most mathematical
operations on it. For a character, you can do things like concatenate (and some mathematical things
believe it or not!).
So lets consider the following simple example. If num1 is a variable with the value 5, and num2 is a
variable with the value 3, then the following code will store the addition of these two values in another
variable called result:
result = num1 + num2;
In this case, when the cout statement executes, num1 and num2 are translated to their stored values and
the operation is performed. We have used the two variables just like they were their actual numbers.
Standard arithmetic operators apply when using variables. Standard order of precedence rules apply too.
For example:
Brackets evaluated first
*, /, and % next (left to right)
+ and - are last
You should use brackets where possible to make code more readable and ensure correct precedence.
With numerical variables, there are some shortcuts we can use when changing their values. Consider if
we want to change the value of a variable by 1. We can write it like this:
num1 = num1 + 1;
This adds one to the value of num1 and stores it in the same variable. We can also write it like this:
num1++;
In this case, the value of num1 is incremented by 1. It is important to note that this is AFTER any other
operation that is performed on the variable.
2.7 Casting
19

2.7
Casting
Because C++ is explicitly typed, sometimes we need to convert a value from one data type to another…
this is known as Casting. This is often required as some operations only work on certain data type.
Casting can happen in two ways. It can happen:
Implicitly… C++ promotes a type to the next highest until types match
Explicitly… we tell C++ to do it for us (we need to do this to demote a value)
With implicit casting we don't do anything… it is all looked after for us. This is often OK, but we need to be
careful that what we expect will happen actually happens. If we want to be sure then we can perform an
explicit cast.
To cast a value we use the static_cast operator
static_cast (expression)
So for example, if we want to explicitly get a rounded version of the value of pi:
float fPi = 3.14159f;
//Store a rounded value in another variable
int roughEnough = static_cast(fPi)
Note, you must be careful with the difference between rounding and truncating! Very important when
dealing with decimal places. In this case, the cast truncates the value for us. So if the value we were
casting was 3.9, we would be storing the value 3 in the new variable.
2.8 Working with Basic Classes and Objects
20

2.8
Working with Basic Classes and Objects
To this point we have been talking about basic primitive data types, like ints and chars. But as we
introduced in the first chapter, C++ is an object oriented language. One part of that is that we can also
declare objects.
In the first chapter, we described how classes can represent both data about a thing (data members) and
what that thing can do (member functions). Well, in order to use that class, we declare an object from
that class. To do that, we follow the same conventions as we have just used for basic data types.
To declare an object from a given class, we simply write:
ClassName objectName;
where ClassName is the name of the class we are deriving the object from, and objectName is the name
we are giving it to refer to it in our code (just like our variables). Easy!
To demonstrate, let's use the built in String class. We will get to using our own classes later on in the unit,
but for now, let us use a provided class that will prove very handy. Before declaring a string object, we
first need to tell our code all about strings. To do that, we #include them:
#include
Once we have done that, we are free to create new string objects in our code, like so:
string myName = "Matt";
Big Deal! I hear you say. Just like a basic data type. Yes, we have declared it in the same way (for now at
least…). But we actually have something a lot more powerful, as not only does it hold data (the value of
the string) but also we have access to a bunch of functions we can run on it. We do this using the dot
notation, which means putting a dot after the object name, and then referring to the function we wish to
call. For example, using the string declared above:
//This displays the value 4
std::cout << myName.size();
// This displays the letter that is at spot 0 (i.e. M)
std::cout << myName[0];
We will explore these concepts in more detail later, but be aware how we declared an object and how we
can call on its functions.
2.9 Variable Scope
21

2.9
Variable Scope
Throughout programming, you will encounter these curly brackets, { }. These brackets are to supply us
with scope and control for our program. Variable Scope relates to the parts of the code that a variable is
able to be accessed. This is a very important feature as for security reasons, you want your variables only
to be accessed by the functions that require it, but you also want all the required functions to have
access.
There are 2 kinds of variable scope:
Global Variables: These variables are usually located at the top of the document or within the header file.
They are able to be accessed by the entire class. They are also the most dangerous of the variables as
any code can change them!
Local Variables: These variables are located within the { } Brackets, and can only be referenced within
the brackets that contain them.
Ideally, you want your variables to get as close as you can to the local level so as to ensure they are not
changed by any code that doesn't need to.
Here is an example to help visually see variable scope :
2.10 Data Output to Screen
22

2.10
Data Output to Screen
When creating a program, we usually have a user that interacts with out program. This user is also more
than likely not the person who built the program and therefore, they need to see things as the program is
running, and also interact with our program. But how can we allow an interaction with them? In most
programs you use, they would have something known as a Graphical User Interface (GUI). GUI's can be
quite complex and for this unit they are too complex for the first few weeks, meaning we need another
way to display information to the user. What we can do is utilise something known as a Console. A console
will allow us to output text to a screen allowing us to tell the user what to do and display any data to
them.
In C++, the command for outputting to the standard output stream (console) is cout, which we use in
combination with << as below,
std::cout << 'Your message here!";
where "Your message here!" is what we want to output. Alternatively, as you have already seen in an
example, we could use a variable to display something to the screen:
std::cout << userNum << " squared is " << result << std::endl;
In this case we are using out integers called userNum and result to build a meaningful sentence for
output. Given a user input of 7, the sentence would be:
7 squared is 49
Note how we used multiple sets of << to build up the sentence with a mix of variables and strings. Also
note the keyword endl on the end. It makes the display finish the line and go to the next line of the
console. A simple little way to help make your output more readable.
2.11 Data Input from the Keyboard
23

2.11
Data Input from the Keyboard
Our user doesn't have to sit there passively. We can also have them inputting data into our program using
the keyboard. This makes our programs much more meaningful!
You can probably guess that we use a similar method to cout. For input we use cin and we use it as in the
example below from earlier:
int main()
{
int userNum = 0, result = 0;
std::cout << "Please enter an integer: ";
std::cin >> userNum;
result = userNum * userNum;
std::cout << userNum << " squared is " << result;
}
Note a few things with the cin line of code. Firstly, the >> are pointing in the opposite direction to that
used in cout. Secondly, they are pointing towards the name of a variable. This means it is going to read in
from the keyboard and store it in the variable called userNum.
In fact, the user will see:
Please enter an integer:
and the program will be sitting there, waiting for the user to type in a number and press "enter". When
they do that, it will read in the value, and proceed with the rest of the lines of code.
Here is an example where it is important to make sure you have declared the right data type, as it will try
and force the data read in from the user into that type. We will discuss later how we can try and ensure
the user does not enter "bad" data.
2.12 File Input/Output in C++
24

2.12
File Input/Output in C++
As well as read in from the user, we can also read data in to our programs from a file stored on the
computer. Also, rather than write things on to the computer screen, we can also write them into a file for
using later on. These tasks are a bit trickier than just reading in values from the user or writing to screen,
but it follows many of the same conventions.
In many respects it works just the same as cout and cin, however rather than use cin to put things in to
variables, or cout to write things to screen, we declare a file stream. Let's show some code to write
something to file and then break it down:
#include
#include
void main() {
std::fstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
}
Let's note the interesting things from this code.
Line 2: First of all, see how we had to #include something else in our code? We need to tell the code that
we are going to be working with files so need access to those capabilities.
Line 5: Next we need to declare a filestream. Think of this as the first part in setting up our "pipe" to our
file for moving data back and forwards.
Line 6: We then need to specify the name of the file we are using. Here it is called "example.txt" and
(with Visual Studio) is located in our project directory, in the same place as our .cpp file
Line 7: Here was are writing the string "Writing this to a file." to the file, as well as a return to make it go
to the next line in the file (\n).
Line 8: It is important as the last thing to close our pipe to the file to make sure it all gets saved OK.
As indicated at the start of this module, we can also read things from a file. Let's look at another example.
Please note that this example assumes there is a file called "numbers.txt" that contains two integer
values on separate lines.
#include
#include
void main() {
2.12 File Input/Output in C++
25
int fileNum1 = 0, fileNum2 = 0, result = 0;
std::fstream myfile;
myfile.open ("numbers.txt");
myfile >> fileNum1;
myfile >> fileNum2;
myfile.close();
result = fileNum1 * fileNum2;
std::cout << "the two numbers multiplied equal " << result;
return 0;
}
Again, let's note the interesting things from this code.
Line 2: We have included fstream as in the earlier example
Line 6: Next we have declared a filestream in the same way.
Line 7: We have specified the name of the file we are using. Here it is called "numbers.txt".
Line 8: This line is a bit different. Here we are using the >> in the opposite direction to indicate we are
reading from the file. It will read the first item in the file (up to a space or an "enter") and store it in the
variable fileNum1
Line 9: Time to read another piece of data! Here we are using a similar line to read the next piece of
data. The file stream will keep track of where we are in the file. It will read the next item in the file (up to
a space or an "enter") and store it in the variable fileNum2
Line 10: Again, it is important as the last thing to close our pipe to the file to make sure the file is not
corrupted. Note that we can close the file before the end of the code… we just won't be able to use it
again without reopening it.
2.13 Namespaces
26

2.13
Namespaces
For input and output, you will have noticed that we have been putting std:: in front of our cout and cin
keywords. This tells the compiler where to find those commands. It is the std namespace.
While this is good in that it tells us exactly where those commands are found, it means we need to repeat
a lot of the same syntax. In C++, we can utilize something known as the Standard Library, a set of
code/commands that are specific to a programming language. cout is a part of this standard library. To
access the ability to use these kinds of functions in our code, we can either use the std namespace or
invoke the std before each element we plan to use from the library.
So our code can be either:
#include
int main()
{
std::cout << "Hello world" << std::endln;
return 0;
}
or we can invoke the std namespace by including the line "using namespace std" at the top of our
program:
#include
using namespace std;
int main()
{
cout << "Hello, world!" << endl;
return 0;
}
Our line to display to the screen now looks much nicer! But it is important to note that it does compromise
understanding of the code somewhat, as someone new who comes to troubleshoot the code may not
know where cout, cin, or endl come from. But the std namespace is a common one to include, so we can
do so in this subject.
2.14 Syntax Building Blocks 1 Summary
27

2.14
Syntax Building Blocks 1 Summary
Here we have covered some basic building blocks to get you writing meaningful programs! You should
now be able to write a basic program that can read in some data, perform some operations on it, and
then output that data. Believe it or not, this is a very powerful concept! You should now experiment with
creating programs that combine all of the concepts we have covered to this point.
Soon we will look at two more control structures that can make your code and programs even more
complex and powerful: decisions and loops.
Please remember to provide any comments here regarding this chapter… what you liked and what can be
improved!
3 Coding Conventions and Style
28

3
Coding Conventions and Style
A programming style is a set of guidelines used to format programming instructions. It is useful to follow a
style as it makes it easier for programmers to understand the code, maintain it, and assists in reducing
the likelihood of introducing errors. Guidelines can be developed from coding conventions used in an
organisation with variations of style occurring for different programming languages. Key elements of
programming style guide include naming conventions, use of comments and formatting (indenting, white
spaces). In some languages (e.g. Python), indenting is used to indicate control structures (hence correct
indentation is required), whilst in other languages indenting is used to improve the visible appearance
and readability of the code (e.g. Java).
The Faculty of Information Technology has a basic published Programming Style Guide, from which much
of this material comes from. You can find it here:
http://intranet.monash.edu.au/infotech/resources/students/style-guide/programming-style.html
In this module, we will cover both the general programming style conventions as outlined in the style
guide, but also those specific to C++ and our class. Therefore, our learning objectives for this chapter are:
Understand the need for a thoughtful and consistent approach to programming style
Understand how choices for variable names and the use of white space can help in the readability
and understanding of code
Understand the need to properly comment program code
3.1 The Need For Consistency!
29

3.1
The Need For Consistency!
Trying to find a universal programming style guide is impossible. Not only do different programming
languages impose different requirements, all coders have a different idea of what they think makes
readable code! This does not mean we shouldn't try to have a style guide though… quite the contrary. It
makes the need for style guidelines even more important for the successful sharing and troubleshooting
of code.
What you have in this module are a number of general guidelines for the styling of your code. Most are
generic, and some mention specific things for C++. You should use these guidelines to inform your
decisions regarding how you write and present your code. The most important thing to remember is that
consistency is essential!
Consistency in how you present your code will help yourself and any reader of your code be able to follow
it, even if they write their code in a different way. If they see how you name your variables, or how you
use blank lines to separate out your code, then they will be able to start to follow it and be able to make
sense of it all. It will also help you late at night when trying to find the bugs in your assignments
3.2 Naming Conventions
30

3.2
Naming Conventions
When naming variables, functions/methods, classes, files etc. it is important to follow a naming
convention, and use correct English spelling (this assists with search/find/replace operations). Naming
conventions are used to improve visual appearance and reduce the effort needed to read and understand
the code. They can vary in different programing languages. The following items are a good guide:
All naming should be descriptive where appropriate.1.
Avoid abbreviation where possible but seek to keep naming an appropriate mix of easy to2.
understand purpose but not too long.
Spaces must not be used. Some languages would use dashes for names (e.g. total-height in Lisp),3.
while other languages would use an underscore (e.g. total_height in Python, SQL). Java uses mixed
case for variables starting with lowercase e.g. totalHeight.
Constants are usually defined as all uppercase using underscores to separate words. e.g.4.
MAX_HEIGHT.
C++ does not have any formal requirements for naming, although it is important to note that some words
cannot be used as variable names. These are typically known as "reserved words" or sometimes
"keywords". These words are ones that are already defined in C++ to do something particular. For
example, you know that "cout" does the job of displaying things to screen. Therefore it makes sense that
this can't be used as a variable name! There are many other reserved words that you must be careful not
to use as a variable name. Just keep that in mind when choosing a variable name.
In our unit, we will adopt the convention of "CamelCase". This is where if a variable name is comprised of
two or more "normal" words, we capitalise them to distinguish them when reading the name (although we
won't be capitalising the first word). So for example, if we have a variable that will store the sum of a set
of numbers representing height, we might call this variable totalHeight. Note the capitalisation we have
used. If the variable name is just one word, then we use the word as usual, with a lowercase first letter.
For constants, we will use the naming convention as described in point 4 above.
For naming of classes and functions, we will stick with the CamelCase convention, although we will
capitalise the first letter of the first word. This will help distinguish them from variables. Note though that
for classes, they are often just one word, which is a noun indicating what the class is, such as Student or
Person.
If you are ever unsure, consistency is king!
3.3 Commenting
31

3.3
Commenting
Comments improve program readability. As with naming conventions, it is important to use correct
English spelling. Please note that different programming languages (dis)allow differernt commenting
styles.
Be consistent with your use of commenting syntax, for example:1.
// This is a line comment
/* This is a block comment
over two lines */
Start each file with a comment at the top describing its contents.2.
Start each class with an accompanying comment that describes what it is for and how it should be3.
used.
Start each function with a comment describing use of the function.4.
Variable names should be descriptive enough not to require commenting. If this is difficult, provide5.
a brief comment at declaration.
Only comment tricky, non-obvious, interesting or important parts of your code throughout6.
implementation.
Follow normal grammatical conventions to ensure readability of comments.7.
3.4 Indenting and Whitespace
32

3.4
Indenting and Whitespace
Indenting and whitespace are all about readability of your code. The last thing you want when
troubleshooting code is to see a dense slab of code staring at you! You want it spaced out in a logical
manner that makes it easy to read. In a way it is like how paragraphs in a book break up the text into
logical parts. Everyone has their own style and preference here, but here are some general guidelines for
using indenting and whitespace:
Indenting and Whitespace requirements for particular languages supersede any general guidelines1.
(such as Python requirements)
Blank lines should be used to separate logical groupings of code2.
Minimum of 2 blank lines should be used to separate functions3.
Be consistent with choice of tabs or spaces for indenting. Adjust tab sizing so as not to be too large.4.
Aim for best readability. Primary importance is that code is easy to read and logically follow. For5.
example:
a = (b + c) * d;
// is more readable than:
a=(b+c)*d
while (true) {}
// is more readable than:
while(true){}
for (i = 0; i < 10; i++) {}
// is more readable than
for(i=0;i<10;i++){}
if (conditionA && conditionB) {
doSomething;
}
else {
doNothing;
}
// is more readable than:
if (conditionA&&conditionB)
{doSomething;}
else{doNothing;}
3.5 Coding Conventions Summary
33

3.5
Coding Conventions Summary
The purpose of this chapter was to give you an insight into the different elements of Coding Style and
Convention, and to provide some reasons why it is important to consider. Remember, good style will help
you troubleshoot and manage your code, and help anyone else who looks over your code to follow it!
Please remember to provide any comments here regarding this chapter… what you liked and what can be
improved!
4 C++ Syntax Building Blocks 2: Selection and Repetition
34

4
C++ Syntax Building Blocks 2: Selection and
Repetition
In this chapter we will look at the selection and repetition control structures. These are major building
blocks of programming, and are a key part of all programming languages.
The learning objectives for this chapter are:
Understand how to implement decisions and the role they play in program design
Understand how to implement loops and when to use each type of loop
4.1 The Selection Control Structure
35

4.1
The Selection Control Structure
Selection is the next main control structure for us to look at. Rather than each line of code executing one
after the other, with selection (also known as decisions), a choice has to be made about whether a line of
code runs, or indeed which line of code should run. Once a decision is made, the appropriate section of
code is run corresponding to the outcome of the decision.
The basic notion of a decision is the same in all programming languages… it is sometimes just the exact
syntax that varies. In this first example, a true/false expression is evaluated, and if true will run the first
statement:
if (expression) {
statement1;
}
Note that something only happens in this IF statement if the expression is true.
There is also a slightly more complex version. In this example, the true/false expression is evaluated, and
if true statement1 is run, otherwise statement2 is run:
if (expression) {
statement1;
}
else {
statement2;
statement3;
}
In this example, statement2 (and statement3) will run if the expression is false. Therefore, in this IF
statement something willalways happen.
In both examples, note the use of the curly brackets. This allows us to run a series of statements
depending on the outcome of the expression. The else component of the example above shows this. Also,
note that after executing the appropriate statement(s), the code then keeps executing from after the IF
statement.
Decisions with 3 or more options can also be represented. 3 options can be implemented as a nested
decision, where you can see the third option is "nested" inside the else component of the IF statement:
if (expression1)
statement1;
else {
if (expression2)
statement2;
else
statement3;
}
In this example, you can see that if expression1 is true, then statement1 will run. If expression1 is false,
4.1 The Selection Control Structure
36
but expression2 is true, then statement2 will run. Otherwise if both expressions are false, then
statement3 will run. Again, in a nested loop, something will always execute. But note here that the order
of expressions is important. Even if both expression1 and expression2 are true, statement1 will be the
only one to run. This is because it is the first one evaluated to true, therefore statement1 will run and the
IF statement will finish.
There are also other options for implementing 3 or more decisions, such as else if and switch statements,
however they are typically specific to different programming languages.
4.2 Expressions
37

4.2
Expressions
Now is the right time to take a slight detour and talk about expressions. That term was used when
introducing decisions, but it is important to clarify exactly what we mean and understand what their
purpose is.
As alluded to, an expression is a statement that evaluates to true or false. It doesn't equal a value, or do
anything else… in the end it can only mean true or false. Let's look at some examples, assuming that we
have two integer variables declared called num1 andnum2.
num1 == 3
In this example, we are comparing the value of the variable num1 with the value 3. Therefore, if num1 is
current equal to the value 3, then this is TRUE. Otherwise, if it holds any other value, it is FALSE.
Therefore, we could use it in an IF statement like this:
if (num1 == 3) {
statement1;
}
else {
statement2;
}
In this case, statement1 will only run if the value of variable num1 is 3, otherwise statement2 will run.
Side note! Notice the use of == (double equals) here? That is important, as it means let's compare what
is in num1 with the value 3, not assign the value of 3 to the variable num1. This is a common mistake so
keep it in mind!
This example was a very simple expression. They can be much more complex than this. For example, we
may want to check two values and the expression be true if both meet a certain condition. This can be
done using an AND to join two smaller expressions together. We can do it like this:
(num1 == 3) && (num2 < 18)
In this case, the expression evaluates to TRUE only if both the value of num1 is 3 and also the value of
num2 is greater than 18. If either part is false, then the entire expression is FALSE.
Alternatively, we can have the expression only need one part to be true for the whole expression to be
true. We do this with an OR, and it can look like this:
(num1 == 3) || (num2 < 18)
If one part of the expression is true then we say the whole expression evaluates to TRUE.
Expressions can be even more complex than this. You can use a combination of evaluations, ANDs and
ORs to build them. When doing this, keep in mind your normal mathematical order of precedence. Most
importantly, use brackets (like we did above) to separate each part to make it much easier to understand.
4.2 Expressions
38
4.3 Selection in C++
39

4.3
Selection in C++
Here we can see examples of both the simple and more complex versions of the IF statement. We can
have a simple statement:
if (score >= 50) {
cout << "You passed!";
}
In this example, a variable called score has its value checked to determine if it should run the statement.
If the value is 50 or over, then the message "You passed!" will be displayed to the screen. If the value is
less than 50, then this IF statement will not doing anything.
We can also have the more complex statement:
if (score >= 50) {
cout << "You passed!";
}
else {
cout << "Sorry, you didn't pass";
}
In this example, the variable score is checked and like before, will display "You passed!" if its value is 50
or over. However, in this case, if the value is lower than 50, then an alternate message will be displayed,
"Sorry, you didn't pass".
We can also have nested decisions. Here is one with 3 outcomes:
if (score >= 50) {
cout << "You passed!";
if (score >= 80) {
cout << "You didn't just pass, you aced it!";
}
}
else {
cout << "Sorry, you didn't pass";
}
This is a bit more difficult to follow, but let's trace it. Consider a score less than 50… this is easy. The else
component will run saying "Sorry, you didn't pass". But what about if score is 50 or more? Well, stepping
through the code it will display the message "You passed". But note then that another IF statement is
checked. In that one, if the score is 80 or more, it will also give us a message that "You didn't just pass,
you aced it!". So in this case we have three distinct outcomes.
Earlier we alluded to the fact we can have more complex decisions that may have more than 3 outcomes.
We have two ways to realise them in C++. The first is to use an else if. This lets us check any number of
expressions, like in the example below:
4.3 Selection in C++
40
if (score >= 80) {
cout << "You got a HD!";
}
else if (score >= 70) {
cout << "You got a D!";
}
else if (score >= 60) {
cout << "You got a C!";
}
else if (score >= 50) {
cout << "You got a P!";
}
else {
cout << "Sorry, but you didn't pass";
}
Note how the last statement catches everything that does not meet the expressions earlier.
Another way to deal with so many outcomes is to use a switch statement. These are a bit different
however, as in C++ we cannot check for a range of values easily. Rather we need to check for specific
values, like below:
switch (letter) {
case 'a':
cout << "a is for alpha" << endl;
break;
case 'b':
cout << "b is for bravo" << endl;
break;
default:
cout << "I don't know that letter?" << endl;
}
As you can see, with a switch statement we check a variable for a specific value, in this case the variable
letter to see if it is an 'a' or a 'b'.
Two important things to note here. First, with the switch anything that does not match a case runs the
default case. Secondly, note the use of the break keyword. We need to have this in our switch statement
to exit it as soon as we have found a case and run its code.
4.4 The Repetition Control Structure
41

4.4
The Repetition Control Structure
The purpose of a repetition control structure is to repeat some step or set of steps multiple times. Its
main purpose is to save us from having to write the same instructions multiple times in the source code,
but it also caters for the case where we don't know how many times we want something to repeat ahead
of time.
Like a decision, expressions are at the heart of repetitions. We keep doing something while some
expression is TRUE. For example:
while (expression) {
statement1;
}
In this case we say that statement1 continually repeats executing while the expression evaluates to
TRUE. As soon as it becomes FALSE, then the loop will finish. Just like with decisions, we can run as many
statements as we need to inside our curly brackets.
This raises a very important part of loops! What if the expression will never actually evaluate to FALSE?
Then this is what we call an infinite loop, as it will never end! The program may eventually crash, or we
would have to force it to stop. But in the vast majority of cases this is not a good thing.
This example is what we typically call a while loop. It is also known as a pre-test loop as before it runs the
statement it evaluates the expression to make sure it should run. This means that the statement may
never run, depending on whether the expression evaluates to TRUE.
If we have a pre-test loop, then it stands to reason that we may also have a post-test loop. This means we
check at the end of the loop whether it should run again. This is often known as a Do… While loop and
looks like this:
do {
statement1;
} while (expression);
Again, it is running while an expression remains TRUE. However in this case you will note that the loop
statement will always run at least once, as it does not check until AFTER the statement has run.
Both of these loops run an indeterminate number of times as it all depends on the outcome of the
expression. But many times we know how many times something needs to run, either explicitly (say 5
times), or implictly (as many times as the number of elements in an array). To do this we often use a for
loop (also known as a counted loop). This loop takes the form:
for (initialisation; test; action) {
statement1;
}
This loop has more than just an expression in the brackets. In fact it has three distinct parts, but they
should all be familiar. To begin, initialisation happens once (at the start). This is typically setting some
variable to an initial value, for example counter = 0. Next, the test happens at the start of each loop. This
4.4 The Repetition Control Structure
42
is just the same as with our while loop, where it is an expression that is evaluated to TRUE or FALSE. For
example, it may be the expression counter < 3. Finally, we have action that happens at the end of each
loop. In the case of our example, it would be changing the value of the variable counter to ensure that the
loop will terminate at some point, for exmaple we may increment our counter by 1.
Therefore, if we assume the example above will run 3 times, the sequence of instructions in the for loop
above would be:
initialisation (set count = 0)
test (check if count < 3)
statement1
action (increment count by 1)
test (check if count < 3)
statement1
action (increment count by 1)
test (check if count < 3)
statement1
action (increment count by 1... it has now gone to value 3)
test (check if count < 3... it is now equal to 3, not less than)
finish
We will see concrete examples of all types of loops later in this chapter.
4.5 Loops in C++
43

4.5
Loops in C++
We have seen how the three types of loops work in theory, so let's look at how they are implemented in
C++.
The while (pre-test) loop looks almost the same as its plain english version that we saw in the previous
module! Here is an example with a little more code to make it a practical case:
char again = 'y';
while (again == 'y') {
cout << "Do You Want To Play Again? (y/n): ";
cin >> again;
}
cout << "OK, catch you later";
Here you can see that we are going to keep asking "Do you want to play again?" until the user enters
something other than 'y'. As long as they keep inputting 'y' it will keep going. If they enter anything else
at all, it will end. When the loop ends, it continues running the code after the loop, which in this case is
the message to say "OK, catch you later".
An important thing to note in this example is that we initialised our variable called again to something
known at the start to ensure the loop runs at least once.
We can actually use the same example to demonstrate how to write a Do… While (post-test) loop:
char again = 'x';
do {
cout << "Do You Want To Play Again? (y/n): ";
cin >> again ;
} while (again == 'y');
cout << "OK, catch you later";
Looks similar! But here you can see that the loop will run at least once, and that is demonstrated by the
fact that we can initialise our control variable again to anything we like.
Our for (counted) loop example will be something different, as it is all about how many times something
runs rather than waiting for a a different kind of condition to be met. Here, we are going to run our loop 9
times, displaying the count each time around the loop:
for (int x = 1; x <= 10; x++) {
cout << x << " ";
}
In this case, the display to the screen will be:
1 2 3 4 5 6 7 8 9 10
4.5 Loops in C++
44
Note that in the case of for loops, you don't have to simply count up by 1 each time. We could do
something different like count down by 2 each time:
for (int x = 10; x > 0; x = x - 2) {
cout << x << " ";
}
In this case, the display to the screen will be:
10 8 6 4 2
The next module will raise questions about when we choose each type of loop.
4.6 How to Choose a Loop?
45

4.6
How to Choose a Loop?
How do we choose between repetition structures? As the programmer, you can decide. There are some
rules of thumb though:
while loops are for loops with possibly zero iterations. These loops check to see if the condition is
meet before looping. So choose this if a loop may run zero or more times.
do…while loops are for loops with a least one iteration; where the program runs the following code
before it checks whether or not to loop another time.
for loops are for counter-controlled loops where you know how many times you want to loop the
following code.
It is important to note that not all programming languages have all three types of loop. This is in part
because you can perform whatever job you need to to with just a while loop! We have the other loops as
often it makes our job easier as a programmer and makes more logical sense to see it represented in that
way.
4.7 Syntax Building Blocks 2 Summary
46

4.7
Syntax Building Blocks 2 Summary
Congratulations! You have now covered the fundamental building blocks of programming. With sequence,
selection and repetition under your belt you can create very powerful programs. You should experiment
putting all of these together in interesting ways to create new and complex programs.
With a firm understanding of loops, we can next loop at how we can better manage our program data
using arrays.
Please remember to provide any comments here regarding this chapter… what you liked and what can be
improved!
5 Arrays and Vectors
47

5
Arrays and Vectors
With repetition under our belts, and with our background in variables, it is time to explore arrays and how
they can improve the way we work with data in our programs. We will also explore a C++ data storage
type called Vectors which have some extra functionality we can use.
The learning objectives for this chapter are:
Understand how to implement basic arrays in C++ and use loops to iterate through them
Become aware of the Standard Template Library
Become familiar with vectors and how we can use them instead of arrays
5.1 Introduction to Arrays
48

5.1
Introduction to Arrays
An array is a "data structure" thats purpose is to allow you to process a collection of data that is of the
same data type, by having a single name by which to refer to the collection.
For example, consider if we need to work with 100 student exam marks in our program. We could have
100 different integer variables to represent these, named examMark001, examMark002, right up to
examMark100. But what would our code look like trying to work with these? It would be a mess! To simply
find the average we would need a lot of code as we would need to not only declare all 100 variables, but
use them in our code to add them all together.
Instead, we could have an array named examMarks that could be used to maintain the collection of exam
marks for all students enrolled in this unit. We can do this, as all the items constituting the array will have
the same data type and they are a logical collection.
Individual data items in the array are called elements of the array, and are identified by not just the
name of the array, but an additional piece of information called the index or subscript. So for our exam
mark example, the name examMarks refers to the collection, and we use the index in square brackets to
refer to a specific element in the array (i.e. a specific mark). It looks like:
examMarks[17]
This example refers to element 17 in the array.
It is important to note that with an array, we can change individual elements without impacting on the
others. So if we added 1 mark for example to examMarks[17], all the other elements remain the same.
So how does this make our code less messy than having 100 individual variables? Firstly we only need to
have one short line to declare the array. Secondly, to process all the elements in an array, we can use a
loop to work through each one. We can do it using a variable and our array name, rather than specifically
naming each element. We will see examples of this in the next module.
5.2 One Dimensional Arrays in C++
49

5.2
One Dimensional Arrays in C++
How do we use arrays in C++? First we need to declare it like we declare any other variable. Here we
need to define not only the type of data, but also the size of the array. We do it as follows:
int examMarks[100];
Here we have defined an array of integers called examMarks that will hold 100 values. It is important to
note that in C++ the index of the first element is in fact 0, and the highest index is 99 (giving us 100
elements).
In this case we have an uninitialised array, meaning we can't be sure what values are stored in the array.
If we want to set initial values (which is a good idea), and we don't have many, we can declare an array as
follows:
int examMarks = {76, 51, 98, 66, 70};
In this case we have declared an array of 5 elements and given the initial values. It would have the same
outcome as the code below:
int examMarks[5];
examMarks[0] = 76;
examMarks[1] = 51;
examMarks[2] = 98;
examMarks[3] = 66;
examMarks[4] = 70;
If we wanted to initialise our array of 100 elements, this is where we can start to use loops to make our
code nice and compact and easy to follow. The code below will declare our examMarks array and initialise
all 100 values to 0:
int examMarks[100];
for (int i = 0; i < 100; i++) {
examMarks[i] = 0;
}
Here you can see how we use a loop and our loop counter to work with each individual element in our
array.
A good habit to get into is to declare a constant to represent the length of the array. That way we have a
permanent way to always know the length of the array:
const int numStudents = 100;
int examMarks[numStudents];
This code defines a constant to represent the number of students we have, and then we use that to define
the size of our array.
5.2 One Dimensional Arrays in C++
50
5.3 Two Dimensional Arrays
51

5.3
Two Dimensional Arrays
We are also able to have two dimensional arrays, where we use two indexes to refer to elements. A visual
representation might be a chess board, where we have an 8×8 board all with each square able to hold
something. We refer to the spot by both its row and column.
Consider our examMarks example. What if we wanted to store all the marks for all students in a subject in
one array, including 3 assignments and the exam for each student. We could do this with a 2D array,
where one index represents the student and another represents what assessment item we are referring
to. Here is a visual representation of this for 5 students:
5.4 2D Arrays in C++
52

5.4
2D Arrays in C++
Declaring a 2D array is the same as a 1D array… we just need to specify an extra dimension. In this case,
we will declare two constants and create a 2D array to hold 4 assignment marks for 5 students:
int NUM_STUDENTS = 5;
int NUM_MARKS = 4;
int marks[NUM_STUDENTS][NUM_MARKS];
We now have an array that we could visually represent as follows:
To access elements, it is just like before, however we need to specify both indexes:
cout << marks[1][2];
Referring back to our visual representation, we are displaying this element:
5.4 2D Arrays in C++
53
Earlier when working with our simple 1D arrays, we saw how we could use loops to initialise all the
elements in our array. Can we still do that with 2D arrays? Of course! Here we need to use nested loops.
The example below will initialise every element to zero:
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 4; col++) {
marks[row][col] = 0;
}
}
So how does it work? It is important to be able to trace the loops. We enter the first outer loop (where row
= 0) and then straight away move into the second loop (where col = 0). We then process the second
inner loop in its entirety (executing the assignment statement 4 times) before exiting that loop. We then
go back to the outside loop, increment our row by 1, and then move into the second inner loop again.
Note that the inner loop is reinitialised and runs from the beginning again. This cycle repeats until the
outer loop meets its end condition and we are done!
The image below provides a visual representation of movement through the elements:
5.4 2D Arrays in C++
54
In the coming modules we will look at more complex use of both 1D and 2D arrays.
5.5 Problem Solving with Arrays
55

5.5
Problem Solving with Arrays
You have been introduced to 1D and 2D arrays, however it is often difficult to know when it is best to use
arrays, and also how we can efficiently process arrays.
As highlighted earlier, there are two main criteria for arrays in C++: they represent only one type of data
(which can be objects as well as basic data types) and it makes logical sense to group them in an array.
Our marks examples made sense, as we had the same type of data and the logical grouping of rows
representing students and columns representing different assignments.
But given we have this logical grouping of items, how do we working with them in an efficient and
meaningful manner? Let's consider our collection of marks as defined as:
int marks[5][4];
Logically, this means we have 5 students and 4 assignments per student. What might we want to do?
Firstly, we may want to tally up the total mark for each student. We could do this using the line of code:
int total = marks[0][0] +marks[0][1] +marks[0][1] +marks[0][2] +marks[0][3];
cout << "Student 0's total score is: " << total << endl;
But this will only do it for the first student! Does this mean we need to repeat this line of code 5 times?
Hopefully the way I have phrased that question made you immediately think of loops! And we can even
streamline our code further by thinking about nested loops.
Recall how we worked through each element in our 2D array when initialising them? In this case we can
do the same thing, but we should consider logically we want to do with each element:
For each element in a row we want to add them together
We then want to display the total to the screen
We then want to reset our total and repeat for all students
So let's translate that into code!
// Outer loop to work through each student
for (int row = 0; row < 5; row++) {
// Reset our total for each student
int total = 0;
// Inner loop to work through each assignment mark
for (int col = 0; col < 4; col++) {
// For each mark, add it to our running total
total += marks[row][col];
}
// Display the total for the current student
5.5 Problem Solving with Arrays
56
cout << "Student " << row << ": " << total << endl;
}
The comments in the code try to explain how the loop works. The outer loop is to work through each
student row. For each student we then:
Reset the variable total to zero
Loop through each mark for the current student row, adding them to the current total
When we have added all marks for the student, we display to the screen
This is a relatively simple example of how we can work with each element in a 2D array. In this case the
trickier part was to be sure what we needed to do for each ROW.
Now what if I want to display the average mark for each assignment (i.e. work with each column, rather
than each row)? What do we need to do?
Initialise a running total variable for each column
Add up each number in the column
Display the average (i.e the total divided by number of marks in the column)
Do we need to change our loop structure from the example before? Yes! But just a little. Let's go down
instead of across so that we work by column and not row:
// Outer loop to work through each assignment
for (int col = 0; col < 4; col++) {
// Reset the running total of each assignment
float total = 0;
// Inner loop to work through the mark for each student
for (int row = 0; row < 5; row++) {
// For each mark, add it to a running total
total += marks[row][col];
}
// Display the average to the screen (total divided by 5)
cout << "Assignment " << col << ": " < }
You can see that it is very similar to the previous example, however we have "swapped" our inner and
outer loops. This may seem straight forward, but it is a very powerful concept in understanding how we
can work with elements in a 2D array.
Whenever working with loops and arrays you should ask yourself "what do I need to do with each
element?".
5.6 Vectors and the STL
57

5.6
Vectors and the STL
In a way C++ lacks a lot of useful functionality. The Standard Template Library (STL) is a collection of
programming work that has been done for us. It contains containers, algorithms, iterators and functions
amongst other things.
A container lets us store and access collections of the same type. Isn't that an array?! Well, kind of… but
not really. STL containers let us do a WHOLE LOT more than we can with an array. There are a number of
different container types in the STL.
One of the most common uses of the STL in games is for the vector class. A vector is often called a
"dynamic array"… an array that can grow and shrink in size as needed. A vector also has a number of
member functions to manipulate the elements.
Vectors are defined like this:
std::vector vectorName;
Obviously if we include the namespace std, then we can ditch the std:: (just like we do with cout). For
example:
vector vMarks;
Important! We do need to include in our code:
#include
In the next module, we will see how we can use Vectors in practice, and when they may be more helpful
than normal arrays.
5.7 Using Vectors
58

5.7
Using Vectors
One of the key advantages to using Vectors is that there are a number of vector functions to help us.
These include:
push_back… this puts data into our vector into the next available spot
pop_back… this pops the last thing in the vector off to us
resize… we can change the size of the vector if we want to manually do it
size… this can tell us how many items are currently in the vector
capacity… this can tell us how many things it could hold
As with any object we declare that has functions, we simply use these with the previously discussed dot
notation. As well as using these functions, we can also use vectors like regular arrays, using indexes with
the vector name… best of both worlds!
Let's look at how we practically use vectors. Consider we have a vector called vMarks declared like in the
previous module:
vector vMarks;
How do we put data in it? We simply call the push_back function, passing in the data as a parameter:
vMarks.push_back(75);
Why do we need to use a function? Recall that vectors manage the size for us (we don't ever have to
define it), therefore the push_back function will ensure that we have enough space and then put it in at
the end. Therefore, in this example this adds the number 75 to the end of the vector. The new element
actually gets the next free index (in array speak). So if the example above was the 3rd element added, it
can actually be referenced by using:
vMarks[2]
The size() member function allows us to get the size of the vector. In this example, it will return the value
3
vMarks.push_back(65);
vMarks.push_back(72);
vMarks.push_back(59);
cout << vMarks.size();
Given a vector also behaves like an array, we can use our standard way of iterating through elements. For
example:
for (int i = 0; i < vMarks.size(); i++) {
cout << vMarks[i] << endl;
}
So as you can see they are a lot like arrays, but a little more is managed for us. We will see in the next
module, however, how they have even more powerful features.
5.7 Using Vectors
59
5.8 Iterators and STL Algorithms
60

5.8
Iterators and STL Algorithms
Another way we can work with vectors and their data is to use an iterator. An iterator helps us traverse
through a vector. It is used as a replacement for a standard integer in a loop variable. The iterator always
refers to a particular element in an array.
Here we use an iterator to work through each element in a vector:
vector::iterator iter;
for (iter=vMarks.begin(); iter!=vMarks.end(); iter++) {
cout << *iter << " ";
}
This looks just like our previous for loop, except for a few things:
we declare an iterator specifically for a vector of ints (vector)
we use the functions begin() and end() to get the bounds of our vector
we use *iter to reference the vector element
The use of a "*" in front of the iterator tells C++ to use the element to which the iterator refers, not the
iterator itself. This is just like a pointer, which is a concept we will cover a bit later in the course.
These examples have been vectors of basic data types… we can also have vectors of objects
As we have only been exposed to strings so far, let's have a vector of string objects instead:
vector vNames;
vNames.push_back("matt");
vNames.push_back("michael");
vNames.push_back("kate");
We could obviously iterate through this vector using a for loop or an iterator as well. In this case if we use
an iterator, we need to declare the iterator as one for a vector of strings, i.e. vector. What if we
wanted to run a function on each of these strings? For example display the length of each string in the
vector? We can simply call the size() function for each element. If we use an iterator, we need to use a
different convention because of what an iterator actually represents. It would look like this:
vector::iterator iter;
for (iter=vNames.begin(); iter!=vNames.end(); iter++) {
cout << iter->size() << " ";
}
If this is a bit confusing don't worry! We will be revisiting the notion of * and -> when we discuss pointers.
But using iterators doesn't seem any easier than using variables and indexes?! That might be so in this
case, however iterators allow us to do a lot more with STL containers. For example, the vector function
begin() returns an iterator, not an integer. They form an important part of using the STL, as many built in
functions are passed iterators, not integers, to reference vector elements.
5.8 Iterators and STL Algorithms
61
Need convincing? How would I add an element inside an array? I would have to find the spot, move
everything along to make space, then put it in. How would I do it with a vector using integers and
indexes? The same way of course! Not with iterators…
Here we use an iterator to insert the number 89 into the second spot in the vector (i.e 1 along from the
beginning of the vector):
vMarks.insert(vMarks.begin() + 1, 89);
Note that we:
call the function "insert" on the vector
pass it an iterator (in this case the start point of the vector plus 1)
give it the value to insert
This puts it in and moves everything along 1 spot. Easy! Similar thing to remove an element:
vMarks.erase(vMarks.begin() + 3);
We could put this erase function call inside a loop that searches for something in the vector first to find
out where it is first. Like inserting, this function deals with moving all the elements to cover the space left
by erasing. This seems like a good time to show you the find() algorithm then!
iter = find(vMarks.begin(), vMarks.end(), 72);
if (iter != vMarks.end()) {
vMarks.erase(iter);
}
else {
cout << "Mark not found!" << endl;
}
Here we used the find algorithm. We give the algorithm the start point of a vector (as an iterator), the end
point, and what we are looking for in the vector. It is in an IF statement because:
If the value is found, the iterator is the first instance in the vector
If the value is not found, the iterator is actually the end point of the vector
Algorithm? Where did algorithms come from?! Well, part of the reason for using the STL are the handy
algorithms that come with it. Most are generic… they can be used on different containers, with different
types of elements. For many, all we need to give it are some iterators.
In order to use them, we also need to place an include statement at the top of our code to use these
algorithms:
#include
Other examples:
random_shuffle(vMarks.begin(), vMarks.end());
sort(vMarks.begin(), vMarks.end());
With both we simply give it a start iterator and an end iterator and let it do all the work (another great
reason to use iterators). The STL is (for the most part) very efficient so these are very useful to have up
our sleeve.
5.8 Iterators and STL Algorithms
62
5.9 Arrays and Vectors Summary
63

5.9
Arrays and Vectors Summary
As you have seen, arrays and vectors provide us with an efficient way to store and work with collections
of data in our programs. They can be tricky to use, so be sure to practice your use of loops and decisions
to process elements in your arrays.
Next we will introduce Functions as a way to have your code branch to perform specific jobs and how
breaking your code up and help with code reuse and troubleshooting.
Please remember to provide any comments here regarding this chapter… what you liked and what can be
improved!
6 Functions
64

6
Functions
To this point we have covered the three primary control structures: sequence, selection and repetition.
There is also another way in which code deviate from simply moving to the line below, and that is to
deviate to another block of code called a function. Functions are a chunk of code that when called do a
specific job.
The learning objectives for this chapter are:
Understand how functions improve the quality, reuse and readability of code
Be able to write your own functions and call them
Be familiar with the fundamental structure of C++ code and understand the need for formal
structures and code layout
6.1 The Purpose of Functions
65

6.1
The Purpose of Functions
Functions (also sometimes known as Methods) allow us to break up our code into more manageable
chunks that contain a section of code associated with a certain "task". We are then able to "call" the
function to run that particular task, and then when finished continue on executing the code where we left
off.
Functions have:
A name (which is what we call)
Arguments (optional) which is data we may need to supply the function to do its job
Return type, where we specify what type of data the function returns back
A body, which are the lines of code associated with the function
While the exact way functions are defined can vary slightly from programming language to language,
they are typically of the following form:
() {
// function body code here
}
Note that every function must have a return type… it will be typically labelled void if nothing is returned.
A function does not necessarily need arguments however, and can be left blank. The body of the function
is located within a set of braces (and therefore have issues of variable scope as discussed earlier!).
6.2 Functions in C++
66

6.2
Functions in C++
Here is an example of a function as implemented in C++, and being called from our main function:
void addNumbers(int num1, int num2) {
int total = num1 + num2;
cout << num1 << " plus " << num2 << " equals " << total;
}
int main() {
cout << "We are about to call the addNumbers function" << endl;
addNumbers(1,2);
}
The output of this code will be:
We are about to call the addNumbers function
1 plus 2 equals 3
Let's break it down. Our C++ programs always start with the main( ) function (no matter where it is
located in a file). Therefore, the line "We are about to call the addNumbers function" will be displayed to
the screen. The next line is a call to our new addNumbers function. Therefore our code will now jump to
the addNumbers function, passing it two numbers: 1 into the variable num1, and 2 into the variable
num2.
From there, the code inside the addNumbers function is executed. The variable total is declared and
assigned the value of the sum of the two numbers. The line "1 plus 2 equals 3" is then displayed. After
that control returns back to where the function was called from.
C++ has an issue to deal with that some languages like Java don't. Before we can actually use a function,
C++ needs to know about it. In many languages your methods can be in any order in your file and any
method calls would work fine as the compiler works it all out for us, but this is not the case in C++. In fact
in our previous example, if the addNumbers function was after our main function (so not yet defined
before we called it) then our code would not compile!
In C++, we need to declare our function so our compiler knows what is coming and where the code you
want to run is located. This can be done like so:
void addNumbers(int num1, int num2);
int main() {
addNumbers(1,2);
}
As you can see above, we declare our function so the compiler is aware that the function is in this
Class/File and we can have our functions in any order in our code. Declaring functions is the best and
most accepted way to ensure your program will not error and is able to access the needed functions it
6.2 Functions in C++
67
requires.
6.3 Calling Functions
68

6.3
Calling Functions
As in our example from the previous section, calling upon functions is very simple.
int main(){
sayHello();
}
void sayHello(){
//print "Hello" to the Screen
}
Under our main() Function we see the line:
sayHello();
This is our calling of the function titled sayHello(). Once this line of code is reached, we then go straight to
our sayHello() function and start performing the code that is located within this function. Once the code
within this function is completed, we return to where we called the function and continue on like
previously.
With our example above, our new code will run line by line like so:
int main() {
{
//Print "Hello" to the Screen
}
}
You can see inside our new main() function where we called our sayHello() Function has been replaced
with the body of the sayHello() Function. This is essentially what is happening in our code and whenever
we call a function. Instead of retyping the entire "task" we can simple type it once and refer the program
to that chunk of code. This is very handy to our organization, simplification and our program task
management.
6.4 Passing Data to Functions
69

6.4
Passing Data to Functions
Now that you know what functions are (a chunk of code that do a task) what happens when we want a
task completed based on certain information? This is when we can utilise the passing of data to functions.
Say we have 3 objects with certain weights (2kg,3kg,5kg) and we want to know what is the sum/addition
of the weights. We need to be able to tell our function what values we want to add up. To do this, we can
write our functions to accept input. This can look like this:
void addition(int a, int b, int c) {
int sum = a + b + c;
}
The above function accepts 3 int values. These 3 int values are read in order into the variables a, b, and c,
and can now be used within the function to perform our task that we wanted. Notice that by writing it as
(int a, int b, int c), we are actually declaring those three variables for use in our function. We need to do
this, otherwise the function will not know what we mean by the variables a, b and c. As previously
mentioned, the scope of our variables is only within the function.
If we were to call our new function in our main() method, it would look like like so:
void main() {
int num1 = 2;
int num2 = 3;
int num3 = 5;
addition(num1, num2, num3);
}
So in this example, the variables in our addition function will be: a = 2, b = 3, c = 5, and we use them as
a, b & c within our addition function. Note than when you pass a value to a function, it does not alter our
previous variable (in this case num1, num2, and num3) it simply sets our function variables to those
values.
We can see above that we create our 3 int values and then used them in the calling of our new function.
As we have called our function and inside our call we have said: addition(int, int, int) our program will now
run the function that is called addition and have 3 int values as its variable inputs in that order.
This is a very important concept! By using this technique, we can actually write and call functions that
have different variable inputs yet have the same name. For example:
addition();
addition(int);
addition(string);
addition(int, int);
addition(string, int);
addition(int, string);
The above examples are all different functions. They have different variable inputs in different orders and
therefore the program knows that they are different functions. If you think about how we call the
6.4 Passing Data to Functions
70
functions, by putting parameters in the brackets after the name, you can see that it will be able to work
out which one to call, as it will look for particular types of data in a particular order.
However, this means that you cannot have functions that have the same amount and type of variables,
are they are seen as being the same by the compiler. For example, below are two functions that are not
allowed to co-exist:
void addition(int a, int b, int c){
//Here is the code to add up stuff.
}
void addition(int rabbit, int bear, int cat){
//Here is the code to add up stuff.
}
Even though our Variable names (a, b, c, rabbit, bear, cat) are different, they are all ints and there are 3
of them in each function. This means that these 2 functions are the same and therefore rendering the
second one useless even if they have different code within the body.
6.5 Returning Data from Functions
71

6.5
Returning Data from Functions
Here we will learn about returning data from our function. Let's revisit our previous example in the
"Passing Data to Functions" module:
void addition(int a, int b, int c) {
int sum = a + b + c;
}
In our example, we pass values into our function and solve our mathematical problem of adding up all of
our passed in variables. But how can we then access that result of adding up our variables and use it in
our main()? This can be achieved using a return function like so:
int addition(int a, int b, int c) {
int sum = a + b + c;
return sum;
}
In our example, we create an int called sum like we did earlier. But in this case we want to get that result
back to our main method. So note two differences to this version. First, we replace void in the function
header with int. This tells the function (and those of us using it) that we will be returning some data, and
it will be of type int (as remember that we used void to tell the function that it would not be returning
anything). Secondly, to actually return the data, we use the return keyword.
What this does is once the line by line code gets to the return step, it exits the function and returns to
where we called the function taking the result value with it.
Here we can see what that looks like in the main() function:
// Remember we need to predeclare our function to use it
int addition(int num1, int num2, int num3);
void main(){
int result;
int num1 = 2;
int num2 = 3;
int num3 = 5;
result = addition(object1, object2, object3);
}
int addition(int a, int b, int c){
int = a + b + c;
return sum;
}
So line by line, we create our int called result. We then create our 3 ints (num1, num2, num3) and assign
them values. So when we reach the next line, the function will be called, passing our variables. We move
6.5 Returning Data from Functions
72
to the function, create sum, add the values up and store them in sum and then reach the returning of the
variable sum.
It is important to note that sum is only available within the addition() function and all that we are
returning is the value that sum holds. In our calling function, that returned value is being assigned to a
variable so that we can use it. So in essence, the function call addition(object1, object2, object3) actually
corresponds to an integer value.
Using this ability in programming is very powerful as we now have the ability to utilise functions to
complete our tasks quicker, easier and more efficiently.
6.6 Overloading Functions
73

6.6
Overloading Functions
When we discussed passing data to functions, we actually touched on a concept called Overloading.
Overloading functions is where you have two or more functions with the same name, that have different
implementations. Why name them the same? Since a function is typically designed to a specific job, we
might have a case where the job is almost the same, but it just needs some different data to do it.
Let's overload this method:
void sayHello() {
cout << "Why, hello!" << endl;
}
To do this, we need to create another method with the same name:
void sayHello() {
cout << "Why, hello somebody!" << endl;
}
But we can't simply have the method be exactly the same, otherwise our system will be confused! So how
can we make the system know which one we want to use while still having the same name?
We can add input to our function, like so:
void sayHello(string name) {
cout << "Why, hello " << name << endl;
}
So now we have 2 functions with the same name, but do 2 different things. It will know which one to run
depending whether we give the function a string when we call it or not. When overloading, we simply
need to ensure that out functions have different inputs to ensure the system knows which function you
want to use out of all your functions that have the same name.
Below is a list of functions that are overloaded and will work as they all have different inputs. Note the
number and types of inputs:
void sayHello(string name)
void sayHello(int number)
void sayHello(bool name)
void sayHello(string name, string lastName)
void sayHello(string name, int number)
void sayHello(int number, int age)
6.6 Overloading Functions
74
6.7 Variable Scope Revisited
75

6.7
Variable Scope Revisited
At this point we should quickly revisit the notion of variable scope. When we first introduced this idea, we
talked about global and local variables. Now that we have covered functions this should make more
sense!
Remember that a variable is only available to the code that is within the same curly brackets (or in the
function if declared in the header) as where it is declared. So consider the variables that are declared in
our function addition:
int addition(int a, int b, int c) {
int sum = a + b + c;
return sum;
}
Here, the variables a, b, c, and sum are only accessible in this function. Therefore these are considered
local. If we tried to refer to them in the calling function then it would not know what we were referring to.
That is why when we discussed passing data back, we put the result in another variable.
We could however declare the variable called sum as a global variable. Below is some code that shows
this as an example:
void addition(int a, int b, int c);
int sum = 0;
void main(){
int result;
int num1 = 2;
int num2 = 3;
int num3 = 5;
addition(num1, num2, num3);
}
void addition(int a, int b, int c){
sum = a + b + c;
}
Here, as the variable sum is declared outside all the functions, all functions in our file can use that
variable. That is why we don't need to declare it in the addition function, or return the data. But this is
bad programming style! Why?
To begin, ANY function in our file can change its value! That might seem like a good idea, but it can cause
all kinds of problems when trying to troubleshoot code.
Secondly, this means that our addition function doesn't operate as a standalone function, as it relies on a
global variable called sum existing. It means we can't really reuse that code anywhere else.
6.7 Variable Scope Revisited
76
As programmers, we should always be aiming for code that is easy to troubleshoot and has the best
chance of reuse.
6.8 Header Files in C++
77

6.8
Header Files in C++
Remember when we mentioned that we had to declare our functions in C++ before we could call them in
our code? With C++ we have access to the power of header files, and they are ideal for declaring our
functions. Header files are a useful tool and function to separate our declarations from our usual .cpp file.
It means that we can quickly look at a header file and see what functions we have access to, what data
they need, and what they will return.
Header files often look like the following:
#ifndef HEADERDEMO_H
#define HEADERDEMO_H
int addition(int a, int b, int c);
#endif
There are two parts worth noting in this header file.
Firstly (the easy part), this allows the user to utilise the function sayHello() throughout our cpp file without
declaring addition(int a, int b, int c) within the .cpp file. What we will need to do though is tell the .cpp file
about our header file. Consider that the code below is our main .cpp file with our main() function and our
addition function:
// Here we #include our header file, like we include iostream
// The " " indicate it is a file of our own
#include
#include "HEADERDEMO_H.h"
void main(){
int result;
int num1 = 2;
int num2 = 3;
int num3 = 5;
result = addition(object1, object2, object3);
}
int addition(int a, int b, int c){
int = a + b + c;
return sum;
}
Secondly, when creating a .h file, we need to ensure we don't have any infinite inclusions. This is when we
get stuck in an infinite look of trying to include our header file. To prevent this, we need to add the other
lines you see above that are not our definitions. These are called inclusion guards.
First we choose a special keyword (in this case HEADERDEMO_H) and make sure the keyword doesn't
exist using #ifndef command (short for "if not defined"). If it is not defined (which is only the case if we
6.8 Header Files in C++
78
haven't included our header file), then we define the keyword and include the code using #define. Finally
at the bottom, we then close our #ifndef statement using #endif
By separating our .h and .cpp, we have a neater looking code that makes reading a lot easier and quicker.
6.9 Functions Summary
79

6.9
Functions Summary
As you can see, Functions are a powerful concept that not only let us organise our code in a logical
manner, but also greatly help code reuse and troubleshooting. Ensure when writing code that you
consider how you can write it in a modular manner, where you have functions to perform specific tasks,
and then call them from your main code. Also ensure that you follow our C++ conventions of using
Header files.
This concept will be expanded further and placed in a new context when we talk about Object Oriented
Design in the next chapter.
Please remember to provide any comments here regarding this chapter… what you liked and what can be
improved!
7 Introducing Object Oriented Programming
80

7
Introducing Object Oriented Programming
Back in the first chapter we let you know a bit about C++ and mentioned that it is an Object Oriented
programming language. But to this point we have really not explored that any further. In this chapter we
will introduce you to Object Oriented (OO) Design and Programming in a bit more detail.
The Learning Objectives for this chapter are:
Understand the foundations of object oriented design
Become familiar with the different components that make up a class in C++
7.1 Object Oriented Design
81

7.1
Object Oriented Design
In this unit, you will learn about an object oriented programming language. The name object oriented
arises from the basic fact that the approach to software development which is so named is based on using
objects to achieve the system goals. It is important to have a clear understanding of what an object is,
and what an object is capable of doing, being, and remembering, in order to write effective object-
oriented programs.
Object oriented (OO) languages attempt to model entities from real life in computer programs. OO
programs consist of collections of interacting objects. These objects are self-contained units consisting of
data, and behaviours that use the data. In essence, it is trying to take the real or perceived world, and
represent it as faithfully as possible in the system.
For example, if in the real world there is a bookshop, in which are found books for sale, and there are
store clerks which process purchases by customers at the sales counter, there could be classes invented
by the programmer to represent different elements of the real world environment.
Examples in this situation could include:
A Book class to represent the physical books that are for sale. Such things as the title and author
and price of the book would be the data represented by objects of this class.
A Clerk class to represent information about the people who work at the store. These objects would
record details of the name of the Clerk, and possibly their payroll ID number or a password to log
on to the sales machine.
However, sometimes we have to represent things which are more abstract, i.e. less physical. For
example, a purchase by a customer is something quite important in a bookshop's information system, but
a purchase is not something in the real world that you can look at, or hold, hear, smell or taste. Rather, it
is an observed event that occurs from time to time. So instead, we need to consider what facts are
important about the event, that we might need to note down for future reference.
Example classes that fit into this nature of class could include:
Purchase - a class that records the time and date of purchase, the name of the customer who made
the purchase, a list of the items that were purchased, the prices at which the items were bought,
the payment method (cash or credit card).
SoldOut - a class that records details about a book which has had all copies sold, that may need to
be re-ordered for future sales.
Another purpose for which classes are used is to record information about the state of affairs of
something at a point in time, which lasts for some period. They can be used to represent concepts.
Example classes of this type include:
Describing a value, e.g. Colour, Shape, Texture, Distance
Describing a configurationor arrangement of objects, e.g. a class called Marriage could be used to
state that two Person objects are married to each other. A class called Enrolment could be used to
state that a particular Student is enrolled for a particular Unit in a particular Semester.
Programming in an object oriented system is basically a matter of finding the set of classes needed,
representing both abstract and concrete things, and then thinking about how to sequence a set of
7.1 Object Oriented Design
82
manipulations on those objects. What do we mean by 'manipulation'? The following are some examples of
what 'manipulation' means in programming:
Recording new data into the system
Recalling previously entered data
Analysing data to discover hidden facts or infer probable facts or make assumptions that are
possibly true
Using data to perform decision making, or for hypothesizing.
For example, the bookstore described above records details about Purchases over the course of the week,
which records data into the system for later analysis. Another class may be responsible for determining
that the latest 'Harry Potter' book is more popular than the newest recipe book from Jamie Oliver. The
program might infer that it needs to place an order for five times as many of the first book than the
second book - an example of decision making or hypothesizing.
As another example, consider a computer program that manages data relating to the leasing of office
space in a multi-storey city building to a variety of tenants, we would likely want to have objects to
represent details about the various offices, and other objects to represent details about the various
tenants (usually businesses).
Information which we might want to maintain about an individual office could include: its space
dimensions (breadth and depth of the floor space), its location in the building (e.g. third floor, north ward),
the types of services it provides (such as air-conditioning, heating, a water service, large meeting rooms,
etc.) Information which we might want to maintain about a business who is leasing an office could include:
the name of the business, the name of the person to send bills to (for rental charges), a telephone
number of the contact person.
7.2 Classes and Objects
83

7.2
Classes and Objects
Just as methods afford a mechanism of modularity by which we can group related statements together,
another mechanism available to us is the class. A class is a grouping of methods, and variables, (and
other things which we will eventually learn about), into a single modular unit, from which we can make
things that are called objects. An object is a representation inside a running program of some thing or
concept, about which we want to store information and perform some kind of processing on that
information. Objects can be conceived of as being a special kind of "value", but are much more
interesting than a value of a primitive type.
Object oriented (OO) languages attempt to model entities from real life in computer programs. OO
programs consist of collections of interacting objects. These objects are self-contained units consisting of
data, and behaviours that use the data. In essence, it is trying to take the real or perceived world, and
represent it as faithfully as possible in the system.
The name object oriented arises from the basic fact that the approach to software development which is
so named is based on using objects to achieve the system goals. It is important to have a clear
understanding of what an object is, and what an object is capable of doing, being, and remembering, in
order to write effective object-oriented programs.
7.3 Deconstruction of a Class
84

7.3
Deconstruction of a Class
We have described what classes represent and how Object Oriented programming is a particular view of
program design. But what does a class consist of in a practical sense? What parts will we need to design
and create?
At its simplest, a class will have a name and a collection of variables (sometimes called Data Members)
and functions (often called member functions). This aligns with our previously described abstraction of
what a class represents. Every object that we create from the class will then have its own instances of
these variables, and if we run the functions on the object, it will use its own data as stored in those
variables. Every object has its own, independent versions of those variables.
But is that all we need to have a fully functioning, and useful, class? Not quite, as this is somewhat
limiting as to how we can use it. As such there are other parts to a class that we need to consider when
designing and coding it. These include:
Constructors: This is the function that automatically runs when we create a new object based on a class.
This is useful as we can initialise variables and perform any other setup that we need to. We will write our
own constructors for most classes that we create, and often we will write more than one!
Destructors: This is a function that automatically runs when an object is destroyed. These are not as
widely used as constructors, as they are are most important if we need any specific clean up of data or
memory to take place.
Static Data Members: We said that an object based on a class gets its own independent version of the
data members to use. What if you want a piece of data to be shared by all instances of a class? Then you
can declare it as static! More on this later.
We will discuss these elements in more detail in the next chapter when we describe how we create our
classes in C++.
7.4 Object Oriented Programming Summary
85

7.4
Object Oriented Programming Summary
Object Oriented Design can be a tough concept to grasp for not only beginner programmers, but
especially for those that have done a bit of programming, but not with an OO mindset. It is important from
this chapter onward to start tackling programming problems by thinking about these OO design
principles. For example, what are the objects inherent in the system, what attributes would describe them
(data members) and what things might they do (member functions). Always try to keep each class
focused on just what job that thing would do, as that will help with code reuse later on.
Never be scared to run your ideas for an OO design past one of your classmates or a teacher before
blazing away with hundreds of lines of code!
And please remember to provide any comments here regarding this chapter… what you liked and what
can be improved!
8 Writing Our Own C++ Classes
86

8
Writing Our Own C++ Classes
To this point we have discussed Object Oriented programming at a fairly theoretical level. You are
probably thinking "That made sense! Sounds easy!". If you are, that's awesome!
Where students often start to have troubles in going from an OO design, to implementing it in C++ code.
In this chapter we will break down a OO design and classes by writing our own. We will look at the code
needed to write a C++ class and see how we use those classes to create objects within our programs.
The Learning Objectives for this chapter are:
Be able to write our own custom classes and use objects based on these classes
Understand the difference between static members
Understand the importance of constructors and destructors in our classes
8.1 Basic Class Structure in C++
87

8.1
Basic Class Structure in C++
In C++, classes take the form of the following:
class EmptyClass{
};
As suggested earlier, the name of the class should be reflective of what it represents. Classes are filled
with their data members and functions between the 2 braces. This will look like so:
class EmptyClass{
private int myInt;
};
Suddenly the name of this class isn't so appropriate!
When creating a class, be aware of the semi-colon. It is a common issue and can be a source of a lot of
different errors if it is missing. (As a lot of semicolons are within C++, CHECK FOR YOUR SEMI-COLONS!).
Note that a class is typically saved in a file that has the same name as the class. This helps easy
readability and troubleshooting of your code.
8.2 Using our Classes to create Objects in C++
88

8.2
Using our Classes to create Objects in C++
Remember that a class is like a template from which things are created. So while we may have a class
called Student for example, that represents everything that describes a student and what it can do, the
class doesn't actually represent an actual individual student. It simply describes what ALL students are
like.
Therefore, to use a class we need to create individual objects based on the class. We have actually seen
how to do this already! We saw in our discussion of variables that we could declare an object based on a
class by simply:
ClassName objectName;
So assuming we had a class called Student we could declare an object called student1 by using the
following line of code:
Student student1;
We will see variations on this declaration shortly.
8.3 Data Members
89

8.3
Data Members
Data members are variables that are associated within a class and hold a piece of "data" that is a
"member" of that class. Data members are usually the "attributes" of an object, but can be anything that
a class requires. E.g. a box object has a "height", "weight", "depth", etc. but it could also be a "location"
or something that the object tracks, yet is not a direct Attribute. Most data members are Private, as you
should usually use public functions to alter data and not alter it directly for a more secure program. (If you
don't, changing the value of a data member is a lot easier and can cause programming and security
issues).
They can look like:
Private int currentCount;
Public int currentCount;
We have started to use the terms "public" and "private" when it comes to declaring our variables, which is
a little different to what we have done in the past. This is because when we declare them in our class, we
have a choice as to how visible they are to code within and outside our class. We have three visibility
modifiers: public, protected, and private.
Public means the data member is available to all objects within your program (or interacting with it). This
can be dangerous as it can allow access to data that shouldn't be accessed. Methods will usually use this
as their access specifier.
Private means the following is only available to the current object that it is contained within. This is
usually ideal for your data members (Variables) as you don't want users to be able to directly access your
values without going through your functions (Your functions may contain checks so it doesn't break your
program or security measures).
Protected is our third piece of terminology and is used when we get to inheritance and polymorphism in
later weeks. This acts similar to private but any child classes can also access the data (see Inheritance
and Polymorphism).
With classes, there are two important things to consider regarding regular data members. When a class
has a data member, it means that when we create an object based on that class, that object gets its very
own copy of that data member that is independent to any other object that may be created from that
class. For example, imagine that we have a class called Student that has an integer data member called
ID. If we created two objects based on the Student class, they would each have their own ID that could be
set to two different values.
It is also important to note that a data member does not exist until we create an object based on the
class. So in our ID example above, no ID's exist until an object is created,
We will revisit both of these issues when we discuss static data members.
8.3 Data Members
90
8.4 Member Functions
91

8.4
Member Functions
A Member Function is a function located in a class. Member functions look like the functions described
under the Function sections and are used as chunks of code with a task associated with them. For
example, consider a function called GetCurrentCount that is located within a class called Counter:
int Counter::GetCurrentCount()
{
return currentCount;
}
You will notice something different about the function header for the GetCurrentCount function defined
above. The name of the function is preceded by the name of the class (in this case Counter). That is
important as it associates that function with its class.
To call a member function from within the same class, you simply need to call its name like we call other
types of functions. For example:
GetCurrentCount();
To call a member function from outside the class, you need to ensure you create an object of that class
and then invoke the required function. For example:
myObject.GetCurrentCount();
Member functions can also be "Static", meaning that they are the same across all objects of that class,
however Static functions are less likely than static members. Static functions are used to only operate on
the static data members which you can read in the next section. These functions can exist outside the
creation of the object.
8.5 Static Members
92

8.5
Static Members
Static Members are different to the Data Members we have discussed previously. Remember, we said that
each object we create has its very own versions of each data member that are independent of other
objects. That is not the case here. A static data member is only one version that is shared by all objects.
Also, normally a Member doesn't exist until an object is created. However with static members, the data
member exists and can be accessed even without having any objects, as it is "owned" by the class itself.
So if I have a Static Member and a normal Data Member in my class, and I create 2 separate object of the
same class the following will apply:
Object 1 will have normal Data Members that are associated only with Object 1
Object 2 will have normal Data Members that are associated only with Object 2
Object 1 and Object 2 will share Static Members with each other.
Static Members are handy when you have a variable that you would like all objects of the same class to
share. E.g.: a count of the number of objects of that class.
Static members are declared in a similar way to Data members, however they have a different code style
(See your unit's guide for coding standards) and they contain "Static" when they are declared. For
example:
public static int currentCount;
8.6 C++ Header Files Revisited
93

8.6
C++ Header Files Revisited
Now that we know all about classes and have seen how to write them, we should take time to revisit good
coding style.
Earlier, we highlighted the virtues of header files, where we could declare our functions so we could easily
then just define them and use them in our main function and our other code. We take the same approach
with classes. A header file allows us to nicely separate declaration from definition.
Again, a header file theoretically also provides a perfect snapshot of what we can do with the class (data
members we can use, functions we can call). If we consider that a header file can tell us the basics of our
functions (name, data we need to give them, what they return), we could also declare our classes in the
header file, so that we it comes to using them in our code, we simply include the header file and we can
use the class and its functions.
So let's create a basic header file for a new class:
#ifndef COUNTER_H
#define COUNTER_H
class Counter {
public:
int getCurrentCount(); // member function
private:
int currentCount; //data member
};
#endif
Note:
our inclusion guards
the class (Counter)
the data members (only one here, currentCount), made private so they can only be changed by our
class functions
the member functions (only getCurrentCount), made public so that we can run them for objects we
create
We could save this in a file called Counter.h and it would neatly declare our class and its data members
and member functions.
But where do we define what our getCurrentCount function does? The best place to do this is in a .cpp file
also named the same as the class. So in a file called Counter.cpp, we would have:
#include "Counter.h"
int Counter::GetCurrentCount() {
8.6 C++ Header Files Revisited
94
return currentCount;
}
Note that we included our header file so it knows about the class, and then we define how our function
works. Therefore, for each class, ideally we will have a .h file declaring the class and its contents, and a
.cpp file defining all the classes functions.
8.7 Constuctors
95

8.7
Constuctors
In OO programming, a Constructor is a chunk of code that is invoked when creating an object. They are a
Member Function and are designed to initialize an object with values or more correctly, an initial state.
This state is designed to allow the programmer to assign values to the data of the newly formed object
during its creation. Constructors must have the same name as a Class so the Class knows what its
Constructor is. A Constructor takes on the form of:
Counter::Counter()
{
numObjects = 0;
}
Here we can see a Constructor that initialises the data member of numObjects to the value of 0. It will do
this when we create a new object… that object will have its numObjects data member set to 0.
We can also create Constructors that take in a value, much like a method takes in a value:
Counter::Counter(int startCount)
{
currentCount = startCount;
numObjects = 0;
}
In the above example, our variable currentCount has been set the value of the integer we passed into our
constructor. This is now known as a parameterised or non-default Constructor and will be explained in the
next section.
8.8 Writing Multiple Constructors
96

8.8
Writing Multiple Constructors
As with functions previously, we can use a similar technique to create multiple constructors.
Constructors that contain multiple different variable inputs (like our functions) are actually different, and
can be selected based on the variables you use when creating the object.
Counter::Counter{ //Default Constructor
numObjects++;
}
Counter::Counter(int startCount){ //Non-Default Constructor
currentCount = startCount;
numObjects++;
}
Like our Functions, the above constructors are different and can be invoked differently by creating objects
like so:
Counter count1; //This will invoke the First Constructor
Counter count2(10); //This will invoke the Second Constructor
C++ also allows us to also use member initialisers. This is a shorthand, and more efficient, way of
initialising variables. It also lets us easily see initialization of variables. Our constructor can now look like
this:
Counter::Counter(int startCount): currentCount(startCount)
{
numObjects++;
}
8.9 Destructors
97

8.9
Destructors
With Creation comes Destruction. With object orientated languages, we have a lot of power within our
code. However a major issue is what's known as Memory Management. With the creation of objects, we
take up Memory within the computer. This memory is a finite resource and must be managed to ensure
you have a function program that doesn't crash/run out of memory. To do this we utilise a technique
called destructors. Much like constructors, they run automatically but instead when an object's lifetime
has ended. Like a constructor, C++ has a default one, but sometimes it's useful to write your own.
Destructors have a name almost the same as the class, like a constructor, however it is preceded with a
tilda (~). They take on the form of the following:
Counter::~Counter(){
numObjects--; //decrease our object count
}
Unlike constructors, there can be only one destructor per class. This is because a destructor runs
automatically and we have no way to tell it to run a different one, like we can by passing parameters with
constructors.
8.10 Writing Your Own Classes Summary
98

8.10
Writing Your Own Classes Summary
In this chapter we looked at creating our own classes for use in our programs, and what the common
elements are. You can now add these custom classes to your programs to create something truly unique!
While our classes will get a little more complex, particularly in their relationship to other classes (through
the use of Inheritance for example), this chapter covered the core elements that most of the classes you
create will have. So if you are able to create your own classes with data members, member functions,
constructors, destructors and static members, then you are well on your way to becoming a gun OO
programmer!
Make sure that you split your class code up appropriately between header and cpp files to ensure the best
reusability, management, and troubleshooting of your code, and be sure to test all elements of them in
your programs. Next up we will look more closely at how we use these classes in our programs to ensure
that you are comfortable with OO design and coding. Have fun!
And please remember to provide any comments here regarding this chapter… what you liked and what
can be improved!
9 Multi-Class Program Design
99

9
Multi-Class Program Design
In the previous chapter we explored many of the parts that go into creating our own C++ classes. It is
one thing to create a class, but another thing to understand how to use them meaningfully in our
programs. It is especially to important to understand how to use multiple classes in our programs and
become familiar with the best ways to split up our code and troubleshoot any problems we may have. For
example, what if we have one class that has a relationship with another class, such as a data member?
Therefore in this chapter we will look at how we use the classes that we have created, in particular more
than one class, and how we use them without getting ourselves in a mess of errors! And if we get into a
mess of errors, how do we troubleshoot?
The Learning Objectives for this chapter are:
Be able to write programs that use more than one user-defined class
Create classes that utilise other user-defined classes
Become familiar with the best ways to structure our code
Be able to troubleshoot programs that use multiple classes
9.1 Creating Programs With Two or More Independent Classes
100

9.1
Creating Programs With Two or More
Independent Classes
Designing a multi-class program is no different to any of the design principles we have discussed earlier.
In fact, when you start designing an object-oriented program, you don't necessarily know how many
classes you will need! You simply break down the problem into its different elements (one or more
classes) and go from there.
So why then do we have a chapter on multi-class program design? Well, while the basic principles are the
same, when you start designing and coding a program that has a number of user-defined classes, the
complexity of the code and its structure inherently gets more difficult to manage. That should make
sense… more code to try and manage, more files in our project, new dependencies between parts of our
code, and more things that can go wrong! Let's start with something quite straight forward, which is a
program that has two or more independent classes.
This is a program where we have identified a number of classes in our program where each class is
independent of the others. By this we mean that while they may be all used in the same program, they
don't reference another user-defined class within their own class. For example consider that we are
creating a computer-based Role Playing Game. In it we might have heroes and monsters. While these two
things may interact within our game, they are discreet entities (for those of you who are thinking to
yourselves "hey! but they may have similar features like health!", just hold that thought… we will revisit
this when we get to inheritance). So when it comes to designing and coding these classes, we can simply
design and code each independent of the other, with no reference to the other class. We can just follow
the process from the previous chapter.
"But won't they fight each other?" I hear you ask. Well yes they will! But it will be the controlling program
that will have them interact… at a class level they don't know about each other. Heroes and monsters are
blissfully unaware of the other and exist independently… it is only when we put them together in the
same program that they will interact.
This is actually a good principle of object-oriented program design. Does a class need to know about
another class in order to do its job? If not, then keep it independent. It allows you to reuse that code later
on with no modification. For example, with independent heroes and monsters you could create a different
game and reuse one of those classes without any need to include the other class.
So how do we use these in our program? To demonstrate, let's pretend we have a Hero class and a
Monster class. Before declaring an object based on either of these, we first need to tell our code all about
them. To do that, we #include them like we have our pre-defined classes. But rather than do it with the <
> characters (like #include ), we need to tell the code about the class declaration which is in our
.h file (like we described in the section "C++ Header Files Revisited"). So we do it like this:
#include "Hero.h"
#include "Monster.h"
Once we have done that, we are free to create new objects in our code, like so:
Hero playerOne;
Monster monsterOne;
9.1 Creating Programs With Two or More Independent Classes
101
Note that in the declarations above, there are no parameters provided. We would need to provide
parameters if our class constructor expected them.
But otherwise it's as easy as that! No different really than how we have used something like strings
previously. What is crucial here is that you have coded your class in a tidy way, split across .h and .cpp
files as described earlier. if you have done this, then the .h file is all you need to include.
9.2 Creating Programs With Interrelated Classes
102

9.2
Creating Programs With Interrelated Classes
In the previous section we saw how we can include and use two independent classes that we have written
within our programs. Easy huh?! But what if the two classes need to be linked somehow?
Here we look at the case where we have identified a number of classes in our program where a class may
be dependent on one more others. By this we mean that one class may need to reference another user-
defined class within their own class. For example consider our Role Playing Game from the previous
section. In it we might also need items, as that is what our hero will collect throughout the game. While
they could be considered independent things, in our game our hero will gather and store them. Therefore
in this case it is important that our character class is aware of the item class. What changes?
Not much really. However in this case our Hero class is going to have to know about the Item class in
order to be able to have a collection of them (so possibly an array of Item objects as a data member). This
adds a little complexity to the code, but also to our coding process. For example what class should I code
first? How do I test?
In this case it makes most sense to code our Item class first. Again, like the previous section, this can be
done just as outlined in the previous chapter, with its own data members, member functions,
constructors, and the like. We start with the Item class as it has no dependencies on any other class and
as a consequence we could compile and test it before creating our Hero class.
Next, we can code our Hero class. One of the data members of our Hero class is going to be a vector of
Item objects. So how do we do this? Well, it is not really any different to how we used our classes in our
main program in the previous section… we need to ensure we include the Item class in our Hero class in
order to be able to use it. To do this, we can simply include it in our Hero.h file. Below is an example of a
basic Hero class header to demonstrate:
#ifndef HERO_H
#define HERO_H
#include "Item.h"
#include
using namespace std;
class Hero {
public:
Hero(string n);
void addItem(Item i);
private:
string playerName;
int health;
int strength;
int dexterity;
int intelligence;
vectorinventory;
9.2 Creating Programs With Interrelated Classes
103
};
#endif
We included the Item header file so the Hero class knows about the Item class. This highlights again why
it is good practice to split our classes between .h and .cpp files.
From here, you can then use these classes in your main program like we have discussed. You should
ensure that in your main program you #include both your Hero and Item class. It doesn't hurt to have
Item included twice throughout our code… the Inclusion Guards will look after it for us!
9.3 Troubleshooting Your Classes
104

9.3
Troubleshooting Your Classes
When we start having multiple classes in our programs, especially those that are interrelated, we may
start having new errors emerge in our code. Not only that, but the coding process also becomes a little
trickier. Oh no! There is nothing to fear though. If you have a methodical approach to coding then you
shouldn't have any troubles at all. The secret is in the order you go about creating your classes and TEST,
TEST, TEST!
Let us revisit the RPG example of the past two sections. Consider in our game we will have our main
program which will need a Hero class, a Monster class, and an Item class, and that our Hero class
interrelates with the Item class as in the previous section. How would you go about coding it? What is
following is simply MY approach to coding it to minimise the chance of errors and provide the most
opportunity for troubleshooting. You can obviously code in any way you like, but a strong word of
warning! Regularly compiling your code will greatly reduce problems. Too often students will blaze away
and code hundreds of lines of code and numerous classes before compiling. This is guaranteed to end in
compile errors and troubleshooting difficulties! This is simply an approach to minimise your grief
First thing would be to code a basic skeleton of your Main program. Just get a Hello World variant or1.
anything compiling and running! That way you have a known, compiling starting point.
Code the simplest class. By this, choose one that has no dependencies to other classes.2.
Integrate your new class into the basic skeleton program. Don't forget to #include the class. To3.
test, simply create a new object based on that class. If that compiles and runs OK then success! For
good testing, create an object utilising each constructor you have written for that class. Be sure to
compile and run after each one so you can find any errors easily.
Move on to the next easiest class and repeat! You may eventually get to a class that includes4.
another class. If you have started with the simplest ones, then this should already be coded, and
can be easily included in your new class. The continue to test as described above.
Such a methodical process will ensure that any errors that emerge should be easy to fix. Beware though,
that the error messages that often surface relating to incorrect class syntax can often be very cryptic!
Common errors to check are:
Does each class have a semi-colon at the end of it?
Does each header file have inclusion guards?
Have you got #include in each place you need to?
If you find any errors, be sure to get them sorted so that you have NO compile or runtime errors. Leaving
any errors lingering will likely only cause more trouble down the stretch!
9.4 Multi-Class Program Summary
105

9.4
Multi-Class Program Summary
In this brief chapter we looked at the methodological approaches to creating programs with multiple user-
defined classes. It was important to look at this, as it is often at this point that students encounter many
different errors for the first time. It is also essential that you continue to code more and more complex OO
programs so that you become comfortable with managing large numbers of classes and lines of code.
By following the simple processes described, you can ensure that you keep errors to a minimum and have
your programs compiling and running with ease. If you have any feedback on this chapter, please feel
free to leave it in the comments section here!
10 Pointers
106

10
Pointers
In this chapter we will look at References and Pointers. Alot of students can struggle with this topic, so we
want you to try and ensure you have a solid understanding of pointers/references before moving on. Both
of these C++ abilities are what can make C++ one of the most powerful languages in computer
programming.
The learning objectives for this chapter are:
Understand the difference of using references with variables and the implications it has
Understand the concept of pointers and be able to implement them in C ++ programs
Understand the difference between the heap and the stack in declaring variables
Survive without having a brain meltdown!
10.1 An Introduction to References
107

10.1
An Introduction to References
A reference is like another name for a variable. It is a new name for an existing thing. References are a
very handy tool to utilise within C++ as they can be deleted (like going out of scope) without affecting the
original object or variable they were referencing.
Declaring a reference is just as easy as declaring a variable. In the example below, we declare a variable
and then a separate reference to that variable:
int score = 1000;
int& myScore = score;
You can see the main difference is that the reference is referring to another variable and also the use of
the & symbol. The & symbol after the data type tells the compiler that this is a reference and not just a
variable. We then tell the reference what it is referring to. Note that when we declare a new reference, we
MUST tell it what its referring to… we can't do it later.
10.2 Using References
108

10.2
Using References
Once the reference is declared like in the introduction to references, you can use the reference name just
as you would the original variable. For example, these two statements will display the same thing:
cout << score;
cout << myScore;
In this case, the variable called score will be increased twice, first directly, and then secondly via the
reference:
score += 100;
myScore += 100;
There are 2 main reasons we use references. The first is to keep global variables to a minimum and the
second is to improve efficiency. Here is an example of the usefulness of references using simple methods
to swap values.:
void byValueSwap(int x, int y){
int temp = x;
x = y;
y = temp;
}
void byRefSwap(int& x, int& y){
int temp = x;
x = y;
y = temp;
}
Above we can see 2 methods in a class that perform the same task, however there is a difference. The
first one doesn't use references and therefor would require returns to pass the new values back to the
main section of code otherwise the values would simply not change due to scope. In the second one
however, because we are using references, this means that we are in fact utilising the variables from the
main section of code and don't need to return anything.
10.3 Constant References and Returning References
109

10.3
Constant References and Returning
References
A major issue with using references by passing them is that this can open up to some dangerous coding
and allow access to things that shouldn't be accessed. What happens if we don't want to change our
referenced variable? Like variables, we can use constants. This method performs the same task as a
normal reference, but it can't change the value of the object or variable it is referring to. All we need to do
is declare our reference like so:
const int& myScore = score;
But how do you know what to pass to a method?
By Value/Variable: When an argument is one of the basic types (no efficiency gains) or when you
don't want the actual variable to be affected
Constant Reference: Efficiency gains without compromising the original
Reference: Efficiency gains and for changing the original variable (but be careful!)
And just like Variables, we can also return references. This is exactly the same as a variable, but we need
to ensure that our return type is a reference, and that our scope can handle this.
10.4 An Introduction to Pointers
110

10.4
An Introduction to Pointers
Pointers are one of the most powerful concepts in C++. They are not a value, like an int or a char, rather
they are a memory address, a location in memory. This is similar to references, but they have more power
and are also more complex. A main function of pointers that you can utilise is that they are like
references, but can be changed to point to a different location after they have been initialised, which you
cannot do with references.
10.5 Pointer Basics
111

10.5
Pointer Basics
The declaration of a pointer is very similar to a reference but we use a different symbol. Pointer
declaration looks like:
int score;
int* pScore = &score;
Note that we do use the reference (&) symbol here. This is because we need to get the address of the
variable called score (the reference) and store that in our pointer, NOT the value of score.
Pointers can also either be not initialised, or be initialised to null, unlike references:
int* pScore = NULL; //or
int* pScore = 0;
Now what happens when we cout << pScore?
We are actually shown the address in memory where the value of score is stored, not the actual value of
score. We might see something like:
0012FF60
To get that value, we need to do something called "dereferencing". To deference, we need to use our new
symbol (*) in front of our pointer variable. This will look like so:
cout << *pScore;
This line would interpret it as the actual value that is at the location pScore is pointing to, not the memory
address.
So with this in mind, as a programmer, you need to remember when to refer to the location in memory or
when to refer to the value at that location. Another example is if we perform a mathematical operation on
our pointer. Consider these two lines of code:
pScore += 500;
is different to:
*pScore += 500;
The first will actually change the value of the memory location that the pointer is pointing to! In this case,
because it is pointing to an integer, it will increment the memory address by 500 "integer sized" chunks,
which could leading to horrible errors and pointing to memory we are not allowed to use. The second line
is actually dereferences the pointer, referring to the value, and will change the value stored at that
location.
It should be noted that the first line is not always bad. We will see cases where we want to do this.
10.5 Pointer Basics
112
10.6 Constant Pointers
113

10.6
Constant Pointers
Like references, sometimes we may want to limit what power a pointer has. Pointers have the ability to be
declared constant in 2 different ways.
Where the pointer to the location can't be changed1.
Where the data at the location pointed to can't be changed2.
To keep the location the pointer points to the same we use this:
int* const pScore = &score;
To keep the data at the pointers location the same we use:
const int* pScore = &score;
Note, we can change the value of the thing we haven't used the const for, and we can also use both
versions of the constant pointers in the same pointer like so:
const int* const pScore = &score;
10.7 Pointers to Objects
114

10.7
Pointers to Objects
Pointers are not just limited to basic data types. They can also refer to objects that we create. Using
pointers to objects is done in the same way we did before:
Person william();
Person* pWilliam = &william;
Here, we create a person object called William and then create a pointer called pWilliam, which we point
to our original object.
There is a difference when dereferencing our objects though! Using the * symbol in front of our object
doesn't work quite the same way. Including the * in front of the pointer will indeed allow us to use the
object it is pointing to, but we have to be careful to be unambiguous what we are dereferencing. For
example, the following line of code will not perform as you may expect:
cout << *pWilliam.GetName();
This is because the order of precedence is to try and run the function BEFORE dereferencing. It will
actually result in a syntax error. Therefore we need to do something like this to remove the ambiguity:
cout << (*pWilliam).GetName();
C++ provides an even nicer way to do it by using the member access operator arrow, which is ->. Using,
it we can now run a function via a pointer as follows:
cout << pWilliam->GetName();
10.8 Passing and Returning Pointers
115

10.8
Passing and Returning Pointers
Passing pointers to functions is very similar to passing references. We just need to make sure we use the
* symbol and that we pass the method references or pointers. So consider that we have a method that
looked like this:
void pointerSwap(int* x, int* y);
As you can see above, our method takes pointers as it's input variables. Then in order for us to call this
method we would need to do something like this:
pointerSwap(&myScore, &yourScore);
Here, you can see that we call the method and we make sure we pass it memory addresses using the &,
which is what a pointer contains. We can't simply pass the variable because our method would interpret
its value as a memory address, not for the actual value's location.
Using our swap example from "Using References", pointers behave in a similar way. Like references, they
wouldn't need the return as they are accessing the variable directly in memory. This can be very handy
for improving efficiency of our coding as well as hiding (somewhat) our variables.
10.9 Pointers or References?
116

10.9
Pointers or References?
Pointers and references have a few key differences that influence our decision about which to use. These
include:
References need to be referred to an object at their creation. Pointers don't need to do this.1.
References that have been created cannot be later changed to reference another object. They refer2.
to the same object throughout their life. Pointers can be reassigned.
References are never null! They will always refer to the object they were created with. Pointers can3.
be created as null, and later changed to refer to an object later.
Pointers can be null and therefore the programmer will need to be aware of checking for null4.
references. Because references are never null, you don't need to do this.
In general, the option to choose a pointer or a reference can be a hard choice as there are no direct rules
for choosing, and as such, it can come down to personal preference or functionality reasons.
10.10 The Heap and The Stack
117

10.10
The Heap and The Stack
Pointers allow us to use different parts of our systems memory. The stack is memory managed by the
system and C++, and when we create a variable, it is popped onto the stack. The Stack can be
envisioned as a pile of books, and the variable we create is placed on top of the pile. C++ will manage
where to place and where to remove variables from our stack itself. C++ is good at managing this, for
example variable scope rules allow C++ to know when to remove things from memory and make space
for other things.
However there may be instances that you would want to manage this yourself. This is where the Heap
comes in. The Heap is dynamic memory that affords us flexibility and efficiency where we can dictate
what memory to use and we can make variables and objects persistent. It can allow us to get around
scope issues (in some ways) that we will see later.
We have to be more careful programmers though, as we have to manage the memory ourselves. Since it
will be our job to clean up, things can be accidentally left in memory with no way to access them or get
rid of them and this can be very bad, especially when working on systems with limited resources. We will
see how to manage this shortly.
10.11 The New Keyword
118

10.11
The New Keyword
Now that we know what the Heap is, how can we use it? We can utilise the keyword "new" when creating
things. Consider how we have created basic data types and objects in our previous examples:
int stackInt = 0;
Counter stackCounter;
We will vary this so that we use the new keyword in the declaration:
int* pHeapInt = new int;
Counter* pHeapCounter = new Counter();
Note two things. Firstly, they are actually declared like pointers. That is because we need to manage the
memory ourselves, so need to keep a proper handle on the memory address. Secondly, we had to use the
new keyword to then create an actual integer/object at the location.
In our "int*" example above, we only allocated memory in our Heap but didn't give it a value. To actually
assign it a value, we can do this like so:
int* pHeapInt = new int;
*pHeapInt = 10;
Or:
int* pHeapInt = new int(10);
Remember, these are pointers and we will need to dereference them to use the values.
We can now create variables on our Heap, but what happens when we want to delete them? Our Stack
used to do this for us, so in our Heap, we will have to manually do this. When we need to delete
something, we simply use the "delete" keyword.
delete pHeapInt;
delete pHeapCounter;
It is important to note though, this will delete the thing the pointer is pointing to, not the pointer itself. So
a pointer called pHeapInt will still exist and have a memory address in it. But what is at that actual
memory address will be removed.
In many cases, our pointers may fall out of scope and thus be removed by C++. However, if that is not
the case, so that we don't try and access that space improperly, it is a good habit to mark it as NULL so
that we know it is no longer pointing to something valid. Therefore, we can simple assign "null" to our
pointer like so:
pHeapInt = NULL;
pHeapCounter = NULL;
10.11 The New Keyword
119
10.12 Cleaning Up Memory
120

10.12
Cleaning Up Memory
Now that you have an understanding of pointers, references and the Stack/Heap, we have given you the
ability to manage memory. But with great power comes great responsibility. You now have the ability to
cause memory leaks. These memory leaks can be very bad!
As an example,consider the following function:
void leak1() {
int* drip1 = new int (17);
}
This would leak memory because when it gets to the end of its scope, the value 17 that is in memory is
not deleted. Our pointer called drip1 will be removed when the function ends, but we will have the value
17 floating in memory, now no longer accessible. This means it will continue to exist, taking up space.
A good habit is whenever you create a "new" keyword, create a "delete" one as well.
void leak1() {
int* drip1 = new int (17);
// code
delete drip1;
}
Remember, for EVERY "new", you need a delete. Here is another example. In this one we create our
pointer and also the value 17 in memory. The next line however points our pointer to another new value
in heap memory, this time 21:
void leak2() {
int* drip2 = new int (17);
drip2 = new int (21);
delete drip2;
}
The above code will cause leaks as the int 17 is still in memory! The pointer changed but didn't remove
the thing it was pointing to. Below you will see how to fix this. We must delete the 17 from memory
before we reassign the pointer to something new:
void leak2() {
int* drip2 = new int (17);
delete drip2;
drip2 = new int (21);
delete drip2;
}
10.12 Cleaning Up Memory
121
Remember, pointers/references/memory can be difficult to understand. Ensure you take your time and go
over this topic again if you feel confused or ask your tutor for help (for any questions)!
10.13 Practical Use of Pointers
122

10.13
Practical Use of Pointers
So how confused are you right now? Not too much I hope! But if you are, don't feel too down… pointers
are a tricky concept to get your head around. One aspects is how they work, but another is when you
would use them in a practical sense. To tackle that second point, let's talk about Linked Lists.
A linked list is another way we can store and manage data. Think of it as an array (i.e a collection of a
type of data), but rather than it being stored sequentially in a block of memory, you can put each bit of
data all over the place in memory. Here is a visual representation:
Linked List Example
Here you can see that each item in a linked list (called a node) is comprised of two elements: the data,
and a link to the next item in the list. For the links, we can use… you guessed it! Pointers!
But how do we create the nodes? Easy! We can simply create a very basic class to represent the node. All
it needs is a data member for the piece of data we want to store, and a pointer to the next item in the list.
For example:
class IntNode {
public int data;
public IntNode* link;
};
In this example, we have created a class called "IntNode", which will represent a node to store integers.
You can see that we have a simple int for the data (so that is the type of data this linked list will store)
and we have a pointer to an IntNode. We have made the data members public for easy access. There is
no need in this case really to hide them and have accessor functions.
To use this, all we need to do is create a new node based on this class, assign a value, and set the pointer
to NULL (to indicate it is the last node in the chain). If we have created a node previously, then we simply
update its pointer to point to the new node. Easy!
10.13 Practical Use of Pointers
123
It is outside of the scope of this unit to cover linked lists in depth, such as how to code them for use.
However, I encourage you to do some extra reading, and look at some code examples of how to use a
linked list. Linked lists can be quite powerful, and they have some advantages over arrays (and
disadvantages though as well!).
Individual array elements can be accessed easily using indexes, which we can't do with a linked list. We
need to start at the start and read through each element until we get to the one we want. But what linked
lists are great for is data sets where we need to insert into the middle of them. For an array, we would
need to do a lot of moving of items inside the array. Not for a linked list though! All we do is find where
we want to put it in, break a link, create some new ones, and it is in! Much easier and more efficient.
Again, do some extra reading if you are keen to know more!
10.14 Pointers Summary
124

10.14
Pointers Summary
Well done on getting to the end of the chapter on Pointers. They can be a tough concept to grasp, and as
long as you have the basic understanding and why they are important, then as you practice with lots of
code examples, they will make more sense and you will become more familiar with the syntax. More than
ever lots of code writing is the key!
Please remember to provide any comments here regarding this chapter… what you liked and what can be
improved!
11 Inheritance
125

11
Inheritance
In this chapter we will look at Inheritance. Inheritance is a very important part of Object Orientated
Design. It is important to get a good understanding in inheritance to make polymorphism easier when we
come to it next chapter.
The learning objectives for this chapter are:
Understand how inheritance can improve our object oriented design
Be able to create classes that use base classes
Be able to overload functions and understand when it is best to do so
11.1 What is Inheritance?
126

11.1
What is Inheritance?
Inheritance is an important part of Object Orientated Programming. Inheritance is when a class inherits
data members and member functions from another class. There are many uses for inheritance, and it can
be a very powerful programming tool. To give you a better idea of inheritance, we'll explain using YOU as
an example.
Among other things, you are a student, and you are also a person. Consider for example we had a class
called person. Inside this class contained all the data members and functions required for a normal base
person. They have a height, weight, sex, eye colour, etc. They also have their methods for each of their
actions and get/sets for their data members.
Now, say we have another class called the student class. The student class contains all the data members
and functions a student would encounter. They have their student id, grades, classes, etc. They also have
all the functions that a student would encounter.
Now hang on, you are a student and also a person. Instead of writing in your height, weight, age, etc. into
the student class, is there a way we can kind of merge the 2 classes together? YES! With Inheritance!
Inheritance allows us to create a student class that uses the person class as a base, allowing us to use the
person classes methods and variables. Because of this, we can also use inheritance for all the teachers,
builders, bus drivers, etc. utilising the person base class. This increases the reusability of our code
dramatically.
11.2 Inheritance in C++
127

11.2
Inheritance in C++
You will remember in previous sections we discussed public and private data variables. Inheritance will
allow us to use a 3rd called protected. Protected works very similar to private however, with inheritance,
we can use the variables within our child classes but still protect them from other code.
Using our person and student example, we will show you how to create your own inheritance within these
2 classes.
Because our person class will be our base class, our variables within this class will have the protected
label on them if they are to be used by the student class. In this example, we are using both header files
and cpp files.
In our person.h file:
protected:
string m_sFirstName;
string m_sLastName;
Our person class will remain the same as any normal class, where we use public, protected and private as
appropriate.
Our student class is where we need to invoke the inheritance ability. This is done by using this in our
student.h file:
class Student : public Person{
public: Student(string first, string last);
…..
…..
};
Note class Student: public Person. This is our inheritance and it means that when we create a student
object, create a base person class that is attached to the student object.
Now that we have inherited the person class, we can access our first and last name variables from the
person class but simply calling in our student.cpp them like this:
Student::Student(string first, string last) {
m_sFirstName = first;
m_sLastName = last;
m_nID = m_nNumStudents++;
}
Now what do our classes have access to?
Our Person class (parent) does NOT have any inheritance from the student class. Any creation of a Person
11.2 Inheritance in C++
128
object will not have any student functions or data members.
Our student class (child) however is different. If we create a student object, we will have access to all the
functions and data members within the person class that is public or protected. We DO NOT have access
to any of the private functions or data members within the person class from the student object.
11.3 What Happens When We Create Child Objects?
129

11.3
What Happens When We Create Child Objects?
Using our example in the previous section, let's think about what happens when we run our student
constructor:
Student::Student(string first, string last) {
m_sFirstName = first;
m_sLastName = last;
m_nID = m_nNumStudents++;
}
The default, parameter-less constructor of the Person class is actually called first, then the constructor for
the Student class is run.
But what if the Person class has a good parameterised constructor that we want to run? What we can do
is utilise this knowledge and actually run 2 constructors during the creation of the Student class. When
creating a child (Student) class we can run both a student constructor and a person constructor of your
choice by calling the constructor you want to run during the child's constructor like so:
Student::Student(string first, string last):Person(first, last){
m_nID = m_nNumStudents++;
}
Above you can see our student constructor where we have added the call to our person constructor at the
end ":Person(first, last)". Now, we don't need to access the protected variables of the person class as they
are now being initialized and given a value in the person constructor that we called. You can also see that
we can use parameterized constructors by passing the "first, last" string variables to the Person class.
11.4 Function Overriding
130

11.4
Function Overriding
What if we wanted a function in our parent class to have a slightly different functionality when used for
the child? Another useful feature of Inheritance is known as Function Overriding. Say we still have our
Person and Student classes. Now in our Person class, we have a function:


void Person::displayJob() {

cout << "You are unemployed" << endl;

}

What we can do is have a function in the student class with the same name, that will override this
function. An example is:


void Student::displayJob() {

cout << "You are a Student" << endl;

}

What happens is when we call our function display job from our student object, it will actually override our
parent class and display the student class function.
Student1.displayJob();
Will display:
You are a Student
But what if we wanted to display the Person class function and not the student one?
This is easy, we simple do this:
student1.Person::displayJob();
This will allow us to display:
You are unemployed
By calling the Parent class before calling the function, we are able to "override" our override.
11.4 Function Overriding
131
11.5 Multiple Inheritance
132

11.5
Multiple Inheritance
To finish off inheritance, another thing you can do is known as multiple inheritances. Multiple Inheritances
is when we inherit from more than just the one parent class. It's a useful tool if you have a lot of small re-
useable classes that you want to turn into one large class. This can be achieved in two ways.
The first is to have inheritance multiple levels deep. So consider this example:
Class A
Class B : public A
Class C : public B
Here Class A is our parent. We could then have a child class based on this class, called Class B. We could
then derive yet another class, this time from class B, called Class C. Here, class C actually has inherited
from both classes A and B.
Secondly, we can do this more directly:
Class C : public A, public B
Here, we explicitly tell Class C to use both class A and B as its parents.
Multiple inheritance brings about an number of issues, relating to things like scope, appropriateness of
functions, and the like. So be prepared to test your child classes well!
11.6 Inheritance Summary
133

11.6
Inheritance Summary
Hopefully you have recognised what a powerful concept inheritance can be. You can now see that
programming is a lot more than just jumping in and writing slabs of code to solve problems… in many
respects the toughest (but most interesting) part is designing your solution, and thinking about how to
structure your code to reduce the amount of coding you need to do, but also to facilitate code reuse later
on.
As with our initial discussions on OO design, it is always important once you have done a design to step
back and consider if it is constructed in the most efficient manner.
As like every chapter, please remember to provide any comments here regarding this chapter… what you
liked and what can be improved!
12 Polymorphism
134

12
Polymorphism
In this chapter we will look at Polymorphism. Polymorphism is when you call a member function that
produces different results based on the type of object it's being called for. This may sound like overriding
functions, however there are a few differences, and in this chapter you will see how useful they can be.
The learning objectives for this chapter are:
Understand how polymorphism can also improve our design, and be able to implement it in our OO
programs
Appreciate the role friend classes can play in our designs
12.1 Revisiting Inheritance and Pointers
135

12.1
Revisiting Inheritance and Pointers
Let's revisit inheritance for a minute. Did you know when you create an object from a derived class (like
Student) that it is also a member of the base class (like Person)?
It makes sense… it was first formed by grabbing all that base class elements and running the base default
constructor. This is an important concept for you to appreciate as it forms the basis of polymorphism
Now, let's get back to pointers. With our Person and Student classes that we used when discussing
inheritance, we could create a pointer for each object in our main program and use the pointer to access
the object's functions. This is nothing too groundbreaking.
But consider that we could declare a pointer to a Person object, but assign it a new Student object. Huh?!
How is that possible?! Consider exactly WHAT a Student object is before moving to the next module for
some further discussion…
12.2 Pointers to Base Classes
136

12.2
Pointers to Base Classes
Going over Inheritance again, when we create a Student object with a Person base class, the object is also
a member of its parent class (Person). We can utilise this in a very cool way when applying it to things like
pointers.
Say we create 2 objects:
Person *person1 = new Person("Matt", "Butler");
Student *student1 = new Student("Jack", "White");
Now let's create a 3rd in a slightly different manner:
Person *person2 = new Student("James", "Murphy");
You can see above, we have a Person pointer that points to a Student object. This works because our
Student object IS a member of its parent class (Person). Now, if we were to create a collection of Person
class objects (remember, a collection like an Array or Vector can only hold one type of data), we could
now add students to this collection as well! This can also allow any other class that has a base of person
as well. So we could have a vector of Person objects containing:
Person *person1 = new Person("James", "Murphy");
Person *person2 = new Student("Jack", "White");
Person *person3 = new Teacher("Matt", "Butler");
This opens a whole new section of Object Orientated programming! We can now have a collection of
objects, such as an Array or Vector, that as long as they are derived form the same parent class, could be
all different types of object.
12.3 Virtual Functions
137

12.3
Virtual Functions
In our previous section, we discussed creating multiple different child objects in a vector of their parent
object types. For example:
Person *person2 = new Student("Jack", "White");
But what if we try to run our functions? What will happen if the Person and Student class both have a
function with the same name? We need a mechanism to be able to make sure the correct function runs.
For example, if we were to call the function displayJob() which is in both the Student class and the Person
class, which function will run?
In this case, the Person class displayJob() function will run. When using polymorphism, the Parent class
functions will always have priority over the child classes, unless we use Virtual Functions.
To ensure the student or teacher displayJob() functions work when we call displayJob() we need to use the
virtual keyword like so when declaring our function in the parent class:
virtual void displayJob();
When we do this, our compiler will find the more appropriate function to call and call that one instead.
Easy!
12.4 Virtual Destructors
138

12.4
Virtual Destructors
There is another function that you would also want to apply the virtual keyword to. That is our
destructors. This is because we need to ensure the correct destructor is called when our object is
destroyed. Again, this is straightforward, as we just need to use the virtual keyword on each of our
polymorphic classes like so:
virtual ~Person();
This will ensure that the appropriate destructor is called for each of the different child/parent class
objects.
12.5 Static Casting
139

12.5
Static Casting
One problem you may have in our previous Person/Student scenario is having a pointer of type base
(Person) pointing to an object of type derived (Student) and trying to run a function that is only in the
derived class. When you try to run our function that is only in the derived class, you will receive an error
as the program may not be aware to search for the function in the derived class.
To combat this issue, we can use something known as the static_cast.
static_cast can perform conversions between pointers to related classes, from the derived class to its
base, and also from a base class to its derived.
Normally, we could call our function by doing this:
Person *person2 = new Employee("Kathryn", "Calder");
person2->employeeSpecificFuntion();
However, this will not work, so instead we need to do something like this:
Person *person2 = new Employee("Kathryn", "Calder");
Employee *temp = static_cast(person2);
temp->employeeSpecificFuntion();
This is extra work, but in the long run, can be both more efficient and powerful, as it allows us to use the
power of polymorphism while not compromising other things we wish to do.
12.6 Polymorphism Summary
140

12.6
Polymorphism Summary
That brings us to the our last major OO Design concept! We will look more closely at good OO design
practice in later chapters, but with Polymorphism covered you now have the main concepts to be able to
tackle very sophisticated programs.
Polymorphism can be difficult to put into practice, so it is essential that you try and tackle as many
examples as possible. Even if a problem may not require complex polymorphic elements, try them to
ensure you can put the concepts into practice.
Please remember to provide any comments here regarding this chapter… what you liked and what can be
improved!
13 Object Oriented Design
141

13
Object Oriented Design
Now that you will be in full swing with your final assignment, now is also a good time to revisit Object
Oriented design. To this point most problems you have been solving have been fairly prescriptive… most
classes you need to write are probably quite obvious. However this is not usually the case! For example,
for the final assignment however you can approach and design your solution as you see best.
Is there any underlying methodology you should follow? While there is not necessarily just one approach
to coming up with a good object oriented design, there are key things you can consider, which we will
cover in this chapter.
The Learning Objectives for this chapter are:
Have an appreciation for object-oriented design principles and be able to apply them to create
more sophisticated C++ programs
13.1 Thinking About Object Oriented Design
142

13.1
Thinking About Object Oriented Design
As alluded to earlier, if writing a program from scratch you often have complete freedom to design and
write it how you like. It is important however to carefully consider HOW you intend to design the solution,
especially when using an Object Oriented programming language.
Why is this the case? There are a number of reasons:
Some designs will make the coding process much easier, both regarding the complexity of code
and number of lines of code
Some designs will allow greater reuse of code either in the program at hand or later programs
Some designs will be easier to follow and facilitate ease of troubleshooting
Each of these themes will re-emerge as we discuss different OO design considerations in this chapter.
13.2 Separating Presentation From Logic
143

13.2
Separating Presentation From Logic
Separating logic from presentation is hopefully an idea that has emerged as we have discussed OO design
earlier. By this we mean making sure what a class does is ONLY what that thing should be able to do.
One thing that a class should not really be responsible for is input/output for example. Why?
It makes the class rely on other libraries (tightly coupled)
If something changes with the I/O library then we may need to reauthor the class
Ultimately it is not always a classes job to deal with I/O… that is often the job of another dedicated class.
Consider we made a simple text-based game of Battleship, complete with basic 2D arrays to store our
ships and guesses. We could write the logic of this, and display simple characters to the screen
representing our game boards. But what if you wanted to convert it from being text based to having
proper graphics?
If you tied your game classes to I/O (such as cin & cout) that becomes a nightmare and you would have to
rewrite a lot of your code! However if you keep your classes focused on only doing just what they are
meant to (i.e. working with the object) then conceivably you could just plug those same classes into a new
"graphics engine".
This is something to keep in mind when designing any OO solution. It won't always be the most
appropriate way to go, especially if it is a very small program. However a simple consideration such as
this can have considerable implications later on.
13.3 Abstract Classes
144

13.3
Abstract Classes
What happens if we had a parent class that should never have an instance created? For example, we
might say that there is never such a thing as just a "Person", rather always different types of people
based on the child classes. The object has to be a "teacher" or a "student"… they cannot simply just be a
"person".
This is called an abstract class. We implement these when we it makes sense to create a class so that we
can numerous create inheriting classes from it, but we want to make sure that we can never have an
instance of that class. In Java these are simply declared as "Abstract". However this is not the case in
C++. In this language we need to revisit our keyword "Virtual" in order to make it abstract.
All we need to do is declare a virtual function in the class but have no definition. For example:
virtual string speak() = 0;
This has now made the class that this function resides in abstract! If we try to create an object based on
this, then we won't be able to compile our program. We can however declare any child objects that utilise
this class.
13.4 What Are Design Patterns?
145

13.4
What Are Design Patterns?
It is worth looking at one new aspect to our Object-Oriented design discussion… design patterns. This
involves imposing more "rules" in our code as to the creation and management of objects.
For example we can create mechanisms to manage how many objects are created as well as what type of
object. An easy way we can do this is to make our constructors private, and create a public function in the
class to manage the object creation. This means we have something else manage the creation of new
objects rather than using the new keyword.
How does that make things better? Well, we can:
Control how many get created
Control what gets created
In practice, we would create:
a constructor as normal, but make it private
a public function that creates a new object and passes it back to the calling function
Therefore you could put whatever logic you like into that function to control the creation of objects. For
example:
Only create one instance (a singleton) of a class
Creates a different object based on what is passed
We will explore these two design patterns in more detail shortly.
13.5 Singletons
146

13.5
Singletons
As mentioned a singleton is a class that allows only one object to be created. can It also be created to
allow a global access point to this one instantiation.
When would these be used? Consider an operating system… it has many occasions where it only wants
one "instance" of something happening at a time. For example, in Windows you only have one instance of
"Explorer" running. Similarly, in OSX you only have one "Finder" process running.
Games are also cases where Singletons are heavily used. For example, a computer game typically only
has one instance of a "game" running at once. By coding it this way, we ensure that the program rules are
enforced.
Let's consider that we want to have a class called "Game" that we want to enforce as a Singleton. So what
does our Game class need to have to make this happen (besides all of the specific game data members
and member functions)?
A data member that is actually an instance of a Game object
A specialised constructor
A function to return the Game object to whatever code has created it and it using it
We can see this example in code below:
class Game {
// Class data member for our single game object
private static Game instance;
// Game constructor, as normal (except private, not public)
private Game() {
...
}
// Static function to create a new Game object
// if one does not exist, and then return it
public static Game getInstance() {
if (instance == null)
instance = new Game();
return instance;
}
// Any other Game related functions can be included
public void doSomething()
...
}
}
The key things to notice are:
13.5 Singletons
147
We have a static data member holding our single game object. It is private so it cannot be directly
accessed by code outside the class
Our constructor is made private so that code outside our class cannot simply create game objects
We have a public static function who's job it is to return the game object from the class. note that it
first checks to see if one already exists. If it doesn't it first creates one before returning it. This is
static so that it can be run directly from the class (as we can't have any instances created)
13.6 Factories
148

13.6
Factories
The Factory method is useful when polymorphism is being used extensively. This is used when our main
program needs an object, but instead of creating it directly using the new operator, it asks the "factory"
class for a new object, providing the information about the type of object it needs.
Think of this like an actual physical factory. We may ask the factory to produce us a particular product,
and it simply return that product. We don't necessarily interface with the particular department in the
factory that would give it to us. The factory instantiates a new product and returns to the client the newly
created product (casted to abstract product class).
Let's look at the code. We could have a file called "Products.h" where we define our classes:
// Main factory class
class product {
public:
static product* createProduct(int type);
int ID;
protected:
product();
};
//Class for product type A
class productA : public product {
public:
productA();
};
// Class for product type B
class productB : public product {
public:
productB();
};
Our .cpp file shows how we can use it:
#include
#include "Products.h"
// Default product constructor
product::product() {
}
// Function that is passed an integer to represent product type
// and then returns a pointer to a new product of that type
product* product::createProduct(int type) {
if (type == 1)
return new productA();
13.6 Factories
149
else if (type == 2)
return new productB();
else
return NULL;
}
// Product A constructor
productA::productA() {
ID = 1;
}
//Product B constructor
productB::productB() {
ID = 2;
}
As you can see this example makes extensive use of inheritance and polymorphism.
13.7 Object Oriented Design Summary
150

13.7
Object Oriented Design Summary
So do you always need to implement these design patterns? Nope! But it is up to you as a program
designer and coder to consider if approaches such as these may be important with implementation of
your classes.
Don't forget, if you have any comments about this chapter, please leave them in the comments here!
14 A Wrap Up Of Our C++ Journey
151

14
A Wrap Up Of Our C++ Journey
Here we are at the end of our C++ journey in FIT2071! Well done on making it to the end! We hope you
have found these materials useful, and that they have helped with your understanding of the many C++
and programming concepts we have covered.
Keep in mind, this is just the beginning of exploring what C++ can do. From here it will take lots of coding
of all different types of programs for you to solidify what we have covered and for you to encounter new
concepts. Never be scared to try something different and unique with your code!
So here we say farewell, and good luck on the rest of your C++ travels

欢迎咨询51作业君
51作业君

Email:51zuoyejun

@gmail.com

添加客服微信: abby12468