Where we left off
- Various linked list algorithms:
- Inserting a node
- Searching for a value
- Deleting a node
- Passing linked lists to functions
- Linked list variations
Textbook Chapter 13
void clear_list(Node *&head) {
while (head) {
Node *temp = head;
head = head->next;
delete temp;
}
}
Today’s topics
- Intro to object oriented programming
- Abstraction terminology
- Classes and objects - defining, creating, using
Textbook Sections 10.2-10.3
Object oriented programming
- So far we’ve been implementing solutions in a procedural style
- The object oriented approach is based on the idea that different objects can be interacted with in a different way
- You can sit on a chair
- You can draw with a pen
- You can (probably) pick up a chair and a pen
- Can you draw with a chair?
- In the OO approach, we can encapsulate data and functions in a
class- an abstract data type that defines how an object can be interacted with
Abstraction
“The act of separating the essential qualities of an idea or object from the details of how it works or is composed” - Nell Dale and Chip Weems


Abstraction in Computer Science
- A key concept that allows us to build complex systems by:
- Understanding the overall system without understanding all the details
- Focus on the parts of the system that are relevant to us
- Use libraries and APIs without knowing how they’ve been implemented
- In general, two types of abstraction:
- Data abstraction - hiding the details of how data is stored and accessed
- Procedural abstraction - hiding the details of how a function is implemented
Procedural abstraction
Say I provide a header file and precompiled object file for the following functions:
// Reads a date formatted as year-month-day from source
void read_date(Date &date, std::istream &source);
// Writes the date to the output stream as year-month-day
void write_date(const Date &date, std::ostream &out);
- How are these functions implemented?
- Does it matter as long as they work?
- All the built-in functions we’ve been using are examples of abstraction!
Data abstraction
- Just as a function’s behaviour can be separated from its implementation, data abstraction separates the properties of a data type from its implementation
- Essential for the design and planning of custom data types
- Every data type has two components:
- Domain - the set of values that the type can take
- Operations - things that can be done with the type
- An abstract data type (ADT) is a data type whose properties (domain and operations) are specified independent of the implementation
Example: int
- The domain of
intis the set of all integers - Operations:
- Arithmetic:
+,-,*,/,% - Comparison:
==,!=,<,>,<=,>= - Assignment:
= - Increment/decrement:
++,--
- Arithmetic:
- How integers are actually implemented is irrelevant to us!
Note: According to our textbook, built-in types are ADTs
Example: a new list type called IntList
- Domain, with some arbitrary decisions:
- Homogenous linear collection of C++
ints - Minimum size 0, maximum size 100
- Access by position starting from
1
- Homogenous linear collection of C++
- Operations:
insert,delete,retrieveat a specific positionsearchfor a valuelength,sort,printthe list
Example: a new list type called IntList
- If I handed you a
.hand.ofile implementingIntList, you could use it without knowing how it works- Internally, is it a linked list? An array?
- Is the space allocated on the stack or the heap?
- Is the length calculated on the fly, or stored in a variable?
- These are all details that you need to decide when implementing an ADT
To implement an ADT, we need to define a class
Classes
A class is a blueprint for creating objects, much like how a
structis a blueprint for creating data structuresstruct STime { int hours; int minutes; int seconds };class CTime { int hours; int minutes; int seconds; void write(std::ostream &out); };A class is a type of object, just like
intorstringorNodeMember functions are accessed using
.or->just like member variables
Objects
- After defining a
class(or astruct), we can create objects of that type - Also called an instance of the class
- The syntax differs from a
structa little:STime now = {5, 0, 0}; // struct CTime bedtime; // class - can't use {} to initialize bedtime.hours = 11; // uh oh, this doesn't work either! - The main difference between a
structand aclassis that the member variables (and functions) of aclassare private by default - private members can only be accessed by other members of the class
Class definition: general form
class ClassName {
public:
// Public member functions (maybe some variables)
private:
// Private member variables and functions
};
- The
publicandprivatekeywords are access modifiers - If you don’t specify one or the other,
privateis assumed - Good style to have
publicinterface first, thenprivateimplementation details
Example: Time class
In general, anything functions that the user of the class needs to access should be public, and anything else should be private - including member variables!
private members
hoursminutesseconds
public members
write(std::ostream &out)set(int h, int m, int s)int compare(Time other)void increment()
Side tangent: setters and getters
- Good practice to encapsulate member variables by making them
private - But this means we need a way to access them from outside the class
- Getters and setters are public member functions that allow us to access and modify private member variables
- This seems like extra work, but it allows us to do things like:
- Check for valid values
- Change the implementation of the class without affecting the user
All this being said, the C++ FAQ recommends avoiding trivial getters/setters
time.h
Common for a class to have its own header file and implementation file (.cpp)
#ifndef TIME_H
#define TIME_H
class Time {
public:
void write(std::ostream &out);
void set(int h, int m, int s);
int compare(Time other);
void increment();
private:
int hours;
int minutes;
int seconds;
};
#endif // TIME_H
Classes Check-in 1/2
How much memory is allocated when the following code is executed?
- 0 bytes
- 5 bytes
- 8 bytes
- 24 bytes
- Undefined
class Student {
public:
void set(int id, const char *name);
void write(std::ostream &out);
private:
char name[20];
int id;
};
Classes Check-in 2/2
What is the main difference between a struct and a class?
- A
structis a type of object, aclassis a blueprint for creating objects structs can have public member variables,classes can’tclasses can have functions,structs can’tstructmembers are public by default,classmembers are private by defaultstructs are allocated on the stack,classes are allocated on the heap
Using classes

- The program using the class is often called the client
- The client program
#includes the header file to use the class - Implementation is in the
.cppfile - compiled separately
Declaring objects
- Just like any other variable, we can declare objects of a class type, or pointers to objects of a class type
// In main.cpp Time now; // object on the stack Time *later = new Time; // pointer to object on the heap now.set(3, 30, 0); // set the time for now later->set(5, 0, 0); // set the time for later - This isn’t going to work just yet, we haven’t actually implemented the class!
- All we’ve done is describe the class specification or interface
Implementing classes
- A
structjust needs its declaration, but for a class we need to implement its member functions (aka methods) - Syntax is a slight modification on the usual function definition:
// in time.cpp ReturnType ClassName::func_name(Parameters) { // Function body } ::is called the scope resolution operator- You’ve seen this already with
std::ostream,std::cout, etc - This allows multiple classes to have functions with the same name, like
set
Implementing the Time::set function
// in time.cpp
void Time::set(int h, int m, int s) {
hours = h;
minutes = m;
seconds = s;
}
- When implementing a member function, you don’t need to use the
.or->operators to access member variables - If you do need to disambiguate, you can use the
thispointer, which is automatically created as a pointer to the current objectthis->hours = h;
Calling member functions
Say we want to find the index position of the word “World” in a string:
Python
hello = "Hello, World!"
pos = hello.find("World")
C++
string hello = "Hello, World!";
int pos = hello.find("World");
- In both languages,
findis a member function of thestringclass - Calling a member function requests that the object perform some function
- In this case: “Hey,
hello! Find the word ‘World’ and give me the index”
How is
findimplemented? No idea! Thanks, abstraction.
Calling member functions of our own class
- Exactly the same:
// in main.cpp Time now; now.set(3, 30, 0); - The
nowobject is automatically passed to thesetfunction as thethispointer - it’s not in the parameter list! - If you have a pointer to an object, you can use the
->operator:Time *later = new Time; later->set(5, 0, 0); - Just like
structs, this is equivalent to(*later).set(5, 0, 0);
Finishing off the class
We have a few more functions to implement:
write- write the time to an output streamcompare- compare two timesincrement- increment the time by one second
The funkiest one is
compare- in addition to the defaultthisparameter, it needs anotherTimeobject
Coming up next
- Lecture: more on classes
- Assignment 3 π - Due Monday, March 25
- Lab: Classes and objects
Textbook Sections 10.2-10.3