What is Object Orientated Programming (OOP)?
Object-oriented programming is the ‘modern’ alternative to procedural programming. It’s important to learn procedural programming first, so you understand what you are writing, but when you start to write programs that are a little more complex, such as mobile game apps, you will love the benefits of tidying up and reducing your code by using OOP. It follows one of the top principles of software development that you learned earlier in the course – DRY – Don’t repeat yourself.
In fact, in the video you’ll watch shortly, you’ll hear the following quote from Uncle Bob (career software engineer, author of ‘Clean Code’, instructor, and developer of many software development principles):
The best functions are those with no parameters!
OOP speeds things up, like building a house using some parts that are already put together for you, such as a bathroom sink unit that contains a tap, plug, plumbing, drawers, and cupboards already put together, rather than all separate pieces of wood and pipe and chrome that you put together one by one.
Advantages of OOP
- Speeds up the coding process (less code to write)
- Reduces code redundancy (unnecessary code/code repetition) (keeps program DRY)
- Reduces errors from typing functions out so many times
- Reduces mistakes by restricting how values can be accessed and manipulated (public/private).
Abstract Data Types (ADT)
OOP in C++ uses Classes and Objects. Classes are what we call an Abstract Data Type (ADT). This is a data type that is determined by the programmer. The programmer defines what values and functions can be used.
The user of the ADT does not need to know any implementation details. Just the expected inputs and output.
Procedural programming and OOP – what’s the difference?
Procedural programming | Object-Orientated programming |
---|---|
Focuses on storing data in variables and writing separate functions | Focuses on creating objects containing related data and functions |
Languages used: Pascal, Fortrain, C | Languages used: Java, C++, PHP, Ruby |
No way to hide any data | Data is more secure, using public/private |
Top-down approach | Bottom-up approach (inheritance) |
Functions-based. Also variables, data structures, subroutines | Object-based. Also classes, methods, properties, interfaces |
Not based on real-world objects | Based on real-world objects, with a state and behaviour |
Code is written for one-time use | Focus on reusable code, DRY |
The four pillars of OOP
OOP is played out in four main ways:
- Encapsulation
- Abstraction
- Inheritance
- Polymorphism
What are these, you ask? Here’s a brief introduction, and then we’ll unpack each one in a bit more detail.
Encapsulation | Grouping together functions (called methods) and data (called properties) that are directly related to each other into one "Object". A fridge object contains data and functions relating to fridges. |
---|---|
Abstraction | Hiding some of the methods and properties in an object to reduce complexity for the user. Why provide a complicated remote, if all the users needs to interact with is a play button? |
Inheritance | When creating a new class (serviced) based on an existing class (base), base class features are inherited, but derived class can also have its own features. An example may include having a new car that has inherited features from a previous. |
Polymorphism |
Poly (many) morphism (forms). We can write a method that will take different forms depending on the type of the object we are referencing. |
For more information, watch mosh explain this in more detail in the following video:
Encapsulation
Grouping together functions (called methods) and data (called properties) that are directly related to each other into one "object". A fridge object contains data and functions relating to Fridges.
Some terms you should know: the functions are called the object’s methods or member functions, the data is called the object’s properties or attributes, and the data is stored in member variables, as these variables belong to the object.
Abstraction
Hiding some of the methods and properties in an object to reduce complexity for the user. Why provide a complicated remote, if all the user needs to interact with is a play button?
Abstraction is giving a general description of something while being non-specific. For example, a ‘triangle’ is abstract, it is a 3-sided polygon with no other specifics, but an ‘equilateral’ is not abstract, it is specific – a triangle with three sides of the same length.
C++ allows the programmer to restrict access to or visibility of some of the implementation details. For example, when creating a complex function, the user of that function doesn’t need to know all the calculations (functions) that happen to make it work, they just need to know what inputs are needed and what result to expect from the function, so the programmer might hide some of the functions and data.
This isn’t new to you in C++, think of all the functions you’ve already been using in your programming. You’ve just called them from the library without thinking about the calculations happening behind the scenes. Take the pow() function for example. It computes the power of a number. When the function iscalled, all the programmer needs to know is a. what inputs are required from me, and b. what result will I get?
Information hiding
A related principle, and part of abstraction, is called Information Hiding, where the goal is to only allow member functions to access and modify the object’s data. This is done by limiting access to some members of an object using these three access modifiers, public/private/protected.
But why would we do this? There are two reasons:
- Protection:
Protects against accidental or deliberate data corruption. - Need-to-know:
As discussed earlier, users don’t need to know all the implementation details happening behind the scenes.
Inheritance
When creating a new class(Derived
) based on an existing class (Base
), Base
class features are inherited, but Derived
class can also have its own features. An example may include cars.
This is what is meant by ‘OOP is bottom-up’. When we create these car classes at the bottom of a chain, they are inheriting their features from the classes above.
Cars
is the base class (think of a class a bit like a category), and the red car represents the BMW
class which is called the derived class, as it has derived it’s features from the base class. The blue car represents the Porsche
class, which is also a derived class.
The BMW
class and the Porsche
class have derived features from the Cars
class, but they also have their own features (properties and methods) which are unique to their class. Imagine the features in a Porsche that wouldn’t be in a BMW and imagine all the features they have in common which can be set in the base class.
We’re not just talking about derived classes inheriting from base classes, but also objects inheriting features from their class.
Inheritance is where a lot of software reuse comes in, so many functions and attributes don’t have to be rewritten anymore, they can simply be inherited.
Polymorphism
Poly (many) morphism (forms). We can write a method that will take different forms depending on the type of the object we are referencing. pourDrink()
could produce one of five flavours here depending on which object its referencing.
Poly means many and morphism comes from the word morphos which means forms. The example above talks about a method/function behaving differently depending on what object it is acting on. So in the soda fountain example above, the pourDrink()
method will pour cola if applied to the cola
object or it will pour raspberry fizz if applied to the raspberry
object. Another example would be if you had a class called Animals
with a method called makeNoise()
, a derived Dog
class or dog
object would output "Woof!"
if that function was run on it, however a derived Cat
class or object would output "Meow!"
if the same function was run on it.
There are two main types: compile-time polymorphism and runtime polymorphism.
Compile-time polymorphism has two types itself, which are operator overloading and function overloading. Whereas runtime polymorphism’s types are function overriding and virtual function.
For now, we will introduce operator overloading with a bit more detail. For more information on the rest of these, you could dig deeper by reading through Polymorphism in C++ and Types of Polymorphism (GreatLearning, 2021).
Operator overloading
Let’s look at the concept of Operator Overloading, it is a type of compiler-time polymorphism.
Operator overloading is a very interesting feature of C++. It allows you to ‘overload’ (or rewrite) the function of an operator. For example, you can define how you want + to behave when used on your class objects. This is used to perform functions on user-defined data types where the program would otherwise not know how to perform functions on them. This way you can operate on different kinds of data types with one operator.
To learn about how to use operator overloading, watch Bucky’s explanation and example in these two videos:
Part A:
Part B:
Introduction to Classes and Objects
Classes are programmer-defined data types, a bit like a template or blueprint for their objects. It requires no memory itself. Objects are instances of Classes, and they hold the data, which will require memory.
The easiest way to understand objects is to look at real-world examples. Have a look at this real-world example of an object in OOP.
Example 1
In this example, the Class is Dog
, which might even be a derived class from a base class called Animals
. An object of this Dog
class might be rufus
. rufus
contains member variables/attributes and member functions/methods. Member variables would be his height
, weight
, and how much food
he eats, and his member functions are run()
, play()
, and eat()
. Some of these functions will be derived from the base class, for example, eat()
is something all animals do, so that would be a derived method.
Example 2
Here is another example, this time the object is a square, which is a member of the class Square
.
Objects are defined just like other variables:
Members are accessed using dot operators:
Its member variable would be the length of the sides, and its member functions would be setting the length of the sides and getting the length of the sides.
Data
side
: the length of square objects side
Functions
setSide()
: function to set the length of the objects sidegetSide()
: function to get/return the length of the objects side
Note that these are two different types of member functions:
getSide()
is an accessor/get/getter type, which accesses a member variable, but doesn’t change it.setSide()
is a mutator/set/setter type, which modifies a member variable.
Let's check out the following video, where Saldina gives an excellent coding example of creating a class and some objects in C++ OOP
Assess specifiers/modifiers
We previously alluded to access specifiers, and Saldina mentioned them in the video, they are:
private
(+
)public
(-
)protected
(#
)
Some things you need to know about access specifiers:
- These determine how the member variables and member functions of a class can be accessed.
- The only exception is that a class or function can be declared as a ‘friend’ of a certain class to allow access to that class’s members.
public
,private
, orprotected
… they don’t need to be in any order.- In class diagrams, which we will look at shortly, a class’ attributes and operations/functions are preceded with either a
+
,-
, or a#
to indicate the type of access allowed.
Have a look at the image below to bring clarity to the different specifiers.
+ Public | - Private (default) | # Protected |
---|---|---|
Members can be accessed from inside and outside of the class | Members can be accessed only from inside the class | Members can be accessed only from inside the class or derived class |
animalCLass ✓ |
animalClass ✓ |
animalClass ✓ ^ dogClass ✓ |
*friend classes/functions ✓ |
*friend classes/functions ✓ |
Classes are also defined similarly to variables.
Notice the last semi-colon, after the closing curly bracket.
Example
In this example, we are declaring a class called Square
using access specifiers
Now the blueprint is set for what an object of this class should contain, as a minimum.
Watch the second part of Saldina's explanation below and then attempt the activity that follows
Class and object activity
To complete this activity:
- create a class for a combined class group of year 1 and year 2 (aged 5-7) school kids called juniors
- set up 5 class objects with their full names (fake ones), ages, and school ‘year’
- print out a list of the objects showing their names, ages, and years.
Your code might look something like this:
What are UML Class Diagrams?
Imagine you are writing a full program now. It’s quite possible that you will need to create many different classes that are all inter-related. For this, you will need to put together a diagram. We have talked about UML diagrams before, click on the link if you need to refresh your mind. Essentially, we are talking about using a universally accepted method to plan and document your object-oriented programs.
A UML class diagram is a structural type UML diagram which will display all the program’s classes including their member data (called attributes) and member functions (called operations), and the relationships between the classes.
Using this layout means it is easy to understand regardless of the programming language you will use.
Read UML class diagram concise tutorial (Develop Paper, 2021) to learn the ins and outs of creating UML class diagrams. Pay special attention to the relationships between classes, we will briefly discuss this shortly.
Classes activities
Use Visual Paradigm Online’s free class diagram builder to create a class to the given specifications. There are 5 practice activities for you to sink your teeth into.
Activity 1:Bank account
- Create a class called
BankAccount
- The account can have an
owner
and abalance
- Use
deposit()
andwithdrawal()
to change thebalance
- Need to be able to print the
owner
and thebalance
- Once the
owner
is set, it can’t be changed - Constructors can be used to initialise objects (you saw this in Saldina’s last video, however we will cover constructors in more detail later), list them at the start of the operators, with no return value.
Feedback
We hope you enjoyed your first play around with class diagram, the tools make it very easy for you, don't they?
Your class diagram should look something like this:
Activity 2: Pizza
- Create a class called
Pizza
- The pizza should have a
name
,cost
, anddiameter
- It should also have a list of
toppings
, make this a vector of strings - We want to add one
topping
at a time to the vector - We want to print the
cost
of the pizza to the console - We want to print a list of all the
toppings
to the console - Create a constructor to initialise objects with the
name
,cost
, anddiameter
.
Feedback
Your class diagram should look something like this:
Activity 3: Circle
- Create a class called
Circle
Circle
has aradius
- We want to print the
radius
- We want to set the
radius
- We want to get the circumference of the
Circle
- We want to get the area of the
Circle
- Create two constructors:
- No arguments = create a
Circle
withradius
of1
- One argument = create a
Circle
with aradius
provided by a parameter
- No arguments = create a
Feedback
Your class diagram should look something like this:
Activity 4: Rectangle
- Create a class called
Rectangle
- It has
length
measurement - It has
width
measurement - We want to print the
length
- We want to print the
width
- We want to assign the
length
- We want to assign the
width
- We want to find out the
area
of theRectangle
- Create two constructors:
- No arguments = create
Rectangle
withlength
of2
andwidth
of1
- Two arguments = create
Rectangle
object withlength
andwidth
from parameters
- No arguments = create
Feedback
Your class diagram should look something like:
Activity 5: Book
- Create a class called
Book
- Has
author
,title
,cost
, andnumber
of pages - We want to get the
author
name - We want to get the
title
- We want to get the
cost
- We want to get the
number
of pages - Create a constructor to initialise an object with:
author
,title
,cost
, andnumber
of pages.
Feedback
Your class diagram should look something like this:
Class relationships
Association | Shows that there is a relationship between these two classes. I.e.: a Cat and Mouse have an association because cats eat mice. |
---|---|
Dependency | Used to show when one class (the client) uses, relies or depends on another class (the supplier). I.e.: a ShoppingCart class uses the Product class to add a product to the cart. |
Inheritance | One class is a "subclass" of another class, and takes on it's features along with its own. Also called generalisation (higher up you go, the more general) |
Aggregation | A type of association, where the sub/child class can exist without the parent class. I.e.: if a teacher is removed from a class, the students can/will still exist. |
Realisation | One class implements the details specified in an interface. I.e.: a stereo performs functions as determined by the interface. |
Composition | A type of association, where the sub/child class can't exist without the parent class. I.e.: if a house is destroyed by fire, so is its' kitchen. |
When you are creating a class diagram you will need to link the various classes together to show how they relate to each other. We use different kinds of arrows to show different kinds of relationships. The image above shows the types of arrows with the relationship types, and on the right, you can see the same with a short description and example of the relationship.
Multiplicity
We will add details to the arrows to define the relationship even further, to indicate how many objects can be in this class in relation to one instance of a class. This is called multiplicity. Here are a few examples.
Expression | Meaning | Example |
---|---|---|
0...1 | Zero or one | Customer can bring their own bike on the bike ride or rent one. Maximum of one bike per person. So, customer’s bike class can be zero or one. |
0...0 | Must be zero | Animal class should have no instances, the instances should come from the child classes such as lion or red panda. Can be written as 0 for short. |
1...* | One or more | In a course, there is one teacher to one or more students. |
1...1 | Exactly one | The car must have an engine, and can only have one engine, so the engine class should be 1…1. Can be written as 1 for short. |
0...* | Zero or more | The courier truck can have zero or more packages. |
m...m | Exact number | The puppy training camp can only go ahead if full and can only take 5 puppies, so, the trainee Puppy class should be 5…5. For this example, it can be written as 5 for short. |
m...n | Atleast and not more | 0…1 means at least zero, and at most one. 5…10 means at least five, and at most ten. A software training workshop needs to have at least 9 and no more than 12 participants: 9…12. |
Watch Zach from Lucidchart explain relationships between classes and how we display these in our diagrams in his UML class diagram tutorial (Lucidchart, 2017)
Here are a few examples for you with More explanation.
Example 1- Association
Example 2-Dependency
An object of the client class relies on/uses the supplier for a method. Exists if changes to one (supplier) may cause changes to the other (client), but not the other way around.
Class 1 depends on Class 2, as seen in this example, Order package uses Payment package.
Example 3: Aggregation
Aggregation is a type of association relationship, it represents a “part of” a relationship. In this example a book is part of the library. The * shows that there can be many books associated with the library, and the 1 shows that there is only one library for each book.
Objects of the library and books have separate lifetimes.
Example 4: Composition
Composition is also a type of association relationship and represents a “part of” relationship. In composition, however, the parts are destroyed when the whole is destroyed. The car registration objects live and die with the car object, they cannot stand alone.
Example 5: Inheritance/Generalisation
The inheritance relationship is often called generalisation, because the higher you go up the diagram the more general the classes get.
Each class down the diagram is more specialised than the one above, it carries all the same methods and attributes, but also has it's own making it less general than the class above. An object of the Saint Bernard class is an ‘indirect’ instance of the mountain dog class.
Inheritance represents an “as is” relationship. For example, a Newfoundland is a mountain dog.
You can think of inheritance relationships as categories and sub-categories.
You can also have multiple inheritances, for example, a Labrador retriever is a cross between a Labrador and a Golden Retriever, it will inherit the features of both the Labrador and the Golden Retriever class.
UML Class diagram activities
Use Visual Paradigm Online’s free class diagram builder to create a UML class diagram to the given specifications. There are 3 practice activities for you to sink your teeth into.
Ensure you include the classes, relationships, and multiplicity.
Activity 1 – Hotel management system
For this activity, you will need to draw a UML class diagram that represents the following requirements for a hotel management system.
- Hotel room bookings can be made by the receptionist (by phone) or by the guest (online).
- Guests can order food items, which will be cooked by the chef and delivered by the hotel attendant.
- Guests can make complaints to the manager.
- The manager is responsible for ordering stock.
- The receptionist needs to be able to print out the bill so the guest can pay it
Feedback
Have a look at this example of a simple hotel management system class diagram (Beriwal,2012)
Activity 2- Airport
For this activity, draw a UML class diagram that represents the following:
- A country can have many airports.
- A flight has an origin airport and a departure airport.
- Planes are required to make flights.
- Passengers go on flights with tickets and luggage.
Feedback
Have a look at this simple airport example (De Nicola, n.d.) and compare it to yours.
Activity 3 – Bank ATM
For this activity, draw a UML class diagram that represents the following:
- Bank, ATM, ATM transaction, withdrawal, transfer.
- Debit card, customer, account, savings account, checking account.
Feedback
Your diagram should look something like the ‘class diagram for ATM’ pictured part way down this article - UML Class diagram examples of common scenarios (EdrawMax, n.d)
There is a saying that practice makes perfect. This is often used in relation to learning new skills. The more you practice, the better you will become at the skill. Go through the practice activities below.
Practice activity 1- removing special characters
By completing this activity, you will be practising the following C++ programming topics:
- Arrays
- Strings
- For Loop.
To complete this activity, you might need to do some of your own research to work out what is the best way to write a program in C++ that will remove all special characters in a string, leaving only letters from the alphabet.
In action, it should look something like this:
Enter a string: Th!sisn0t@v5r1g00d#x$mpl& Output string: thsisntvrgdxmpl
Feedback
There are a few different ways to approach this, but whatever method you chose, you should have finished up with the ability to enter a string containing special characters, and then had the program output the string with only the alphabet characters, as illustrated below.
Practice activity 2- calculating time
By completing this activity, you will be practising the following C++ programming topics:
- Structure
- Function
- Pointer to structure.
To complete this activity, you will need to write a program in C++ that will take in two amounts of time and output the difference between them in hours, minutes, and seconds.
You are aiming to see something like this on your console:
Enter bigger time length. Enter hours, minutes, and seconds on their own lines: 72. 52 20 Enter smaller time length. Enter hours, minutes, and seconds on their own lines: 72 42 20 TIME DIFFERENCE: 72:52:20 - 72:42:20 = 0:10:0
Practice activity 3- Guess the random number
For this activity, you will need to write a game in C++ that will allow the player to make multiple guesses until they find the correct random number that was generated by the program.
Just a few notes before you begin:
This is the sort of output you are aiming to create:
rand()
does not produce a truly random number, but a pseudo-random value in a sequence of values ranging from 0 toRAND_MAX
.- It is better to use
srand()
to set a random starting point in the sequence. - You initialise the random number generator using a seed. The most accepted way to do this is to use time as the seed, as the starting time of each game should be random. It will look like this:
srand(time(0));
- Your program will need to include the time header:
#include<time.h>.
- Now, the program will start generating numbers from a different point in the sequence each time it runs, depending on the time when it executes, making it appear less predictable than if you had simply used
rand()
.
This is the sort of output you are aiming to create:
Guess the Random Number Game
Enter a number between 1 and 100 : 75
Too high!
Enter a number between 1 and 100 : 35
Too low!
Enter a number between 1 and 100 : 55
Too low!
Enter a number between 1 and 100 : 65
Correct! You got it in 4 guesses!