9.
Objects and Classes
9. Objects and Classes
Object-oriented programming (OOP) involves programming using objects.
CREATING AN OBJECT:
The state (properties or attributes) of an object is represented by data fields with their current
values. The behavior (actions) of an object is defined by functions. For example, a circle object
has a data field, radius, which is the property that characterize a circle. We may define a function
named getArea() for circle object to return the area of the circle.
An instance of a class is an object. Instantiation is creating an instance. We may create many
instances of a class.
A C++ class uses variables to define data fields and functions to define behaviors.
Constructors are functions of a special type that a class provides to perform initializing actions.
Constructors must have three properties:
• Have the same name as the class itself.
• Do not have a return type, not even void.
• Invoked when an object is created.
Class Variable vs Instance Variable:
The class variable is the variable which is associated to the class (its value is not changed when
instantiation) while the instance variable is the variable which is associated to the instance
(different instances of the same object has different values of the instance variable).
-1-
9. Objects and Classes
#include <iostream>
using namespace std;
class Circle{
public:
double pi = 3.14159; // Class variable
double radius; // Instance variable
// Construct a circle object without arguments
Circle(){
radius = 1;
}
// Construct a circle object with arguments
Circle(double newRadius){
radius = newRadius;
}
// Return the area of this circle
double getArea(){
return radius * radius * pi;
}
}; // Must place a semicolon here
int main(){
Circle circle1; // Create a circle object whose radius is 1
Circle circle2(5); // Create a circle object whose radius is 5
cout << circle1.radius << endl;
cout << circle2.getArea() << endl;
circle2.radius = 2; // Modify the radius of circle2 Circle object
cout << circle2.getArea() << endl;
return 0;
}
NB. A semicolon (;) is essential to be places after the closing curly brackets (}) of defining a
class.
-2-
9. Objects and Classes
ACCESS OBJECT’S DATA AND FUNCTIONS:
After an object is created, its data can be accessed and its functions invoked using the dot operator
(.), also known as the object member access operator. The data field is referred to as instance
member variable or simply instance variable while the function is referred to as instance member
function or instance function. A calling object is an object on which an instance function is
invoked.
Data fields may be initialized in the constructor using an initializer list:
...
class Circle{
public:
double radius;
Circle()
: radius(1) // No semicolon here
{
// Additional statement if needed
}
Circle(double newRadius){
: radius(newRadius) // No semicolon here
{}
}; // Must place a semicolon here
NB. A class may be defined without constructors. In this case, a no-arguments constructor, called
default constructor, with an empty body is implicitly defined in the class.
...
class Circle{
public:
double radius;
// Implicitly a default constructor with no arguments is defined
/*
Circle(){
-3-
9. Objects and Classes
}
*/
// Return the area of this circle
double getArea(){
return radius * 3.14159;
}
}; // Must place a semicolon here
Anonymous object is an object which is created without naming it to use it only once.
...
int main(){
// Create anonymous objects
cout << Circle().radius << endl;
cout << circle(5).getArea() << endl;
return 0;
}
NB. In C++, to create anonymous object using no-arguments constructor, we have to add
parentheses after the constructor name (e.g., Circle()) while creating a named object using no-
arguments constructor, we cannot use parentheses after the constructor name (e.g., Circle
circle1).
NOTES:
• A class is also a data type.
• We can use either primitive data types or another class to define the class data fields.
• We can use the assignment (=) operator to copy the contents from one object to the other.
• The object name is constant. It cannot be reassigned to represent another object.
-4-
9. Objects and Classes
SEPARATING CLASS DEFINITION FROM IMPLEMENTATION:
Importance of :
• It makes the class easy to maintain.
• It protects the software provider’s intellectual property as it hides the source code.
Class definition Class implementation
• Lists all the data fields
• Lists constructor prototypes Determine how the class operates
• Lists function prototypes
File extension is .h File extension is .cpp
Circle.h
class Circle{
public:
// The radius of the circle
double radius;
// Construct a default circle object
Circle();
// Construct a circle object
Circle(double);
// A function that return the area of the circle
double getArea();
};
Circle.cpp
#include "Circle.h"
// How to construct a circle object with a default radius = 1
Circle::Circle()
{
radius = 1;
}
// How to construct a circle object with a specific radius
Circle::Circle(double newRadius)
{
radius = newRadius;
}
// How to calculate and return the area of the circle
-5-
9. Objects and Classes
double Circle::getArea()
{
return radius * 3.14159;
}
main.cpp
#include <iostream>
#include "Circle.h"
using namespace std;
int main(){
Circle circle1;
Circle circle2(5);
cout << circle1.getArea() << endl;
cout << circle2.getArea() << endl;
return 0;
}
NB. The :: symbol is known as binary scope resolution operator which specifies the scope of a
class member in a class. Circle:: preceding each constructor and function is the Circle class
tells the compiler that these constructors and functions are defined in the Circle class.
NB. Such a program that uses the class is often referred to as a client of the class.
PREVENTING MULTIPLE INCLUSIONS:
Inclusion guard prevents header files to be included multiple times. Including a header file
multiple times results in a compile error indicating that there are multiple definitions for the
header.
Circle.h
#ifndef CIRCLE_H // Stands for if not defined
#define CIRCLE_H
class Circle{
-6-
9. Objects and Classes
public:
// The radius of the circle
double radius;
// Construct a default circle object
Circle();
// Construct a circle object
Circle(double);
// A function that return the area of the circle
double getArea();
};
#endif
Head.h
#include "Circle.h"
Circle.cpp
#include "Circle.h"
#include "Head.h"
// How to construct a circle object with a default radius = 1
Circle::Circle()
{
radius = 1;
}
// How to construct a circle object with a specific radius
Circle::Circle(double newRadius)
{
radius = newRadius;
}
// How to calculate and return the area of the circle
double Circle::getArea()
{
return radius * 3.14159;
}
main.cpp
#include <iostream>
#include "Circle.h"
using namespace std;
-7-
9. Objects and Classes
int main(){
Circle circle1(5);
cout << circle1.getArea() << endl;
return 0;
}
NB. Any statement preceded by the sign (#) is preprocessor directive.
INLINE FUNCTIONS IN CLASSES:
When the function is implemented inside a class definition, it automatically becomes an inline
function. This is also known as inline definition that improve performance. To make the function
an inline function in the implementation file, the function is preceded by inline keyword.
Circle.h
#ifndef CIRCLE_H // Stands for if not defined
#define CIRCLE_H
class Circle{
public:
// The radius of the circle
double radius;
// Construct a default circle object
Circle() // Inline definition
{
r = 1;
}
// Construct a circle object
Circle(double);
// A function that return the circumference of the circle
double getCircumference() // Inline definition
{
return 2 * r * 3.14159;
}
// A function that return the area of the circle
double getArea();
};
inline double Circle::getArea() // Inline definition
-8-
9. Objects and Classes
{
return radius * 3.14159;
}
#endif
Circle.cpp
#include "Circle.h"
#include "Head.h"
// How to construct a circle object with a default radius = 1
// How to construct a circle object with a specific radius
Circle::Circle(double newRadius) // Not inline definition
{
radius = newRadius;
}
DATA FIELD ENCAPSULATION:
Encapsulation is bundling of data with the mechanisms or methods that operate on the data while
information hiding is making the data fields private protects data and makes the class easy to
maintain.
Cons of public data fields:
• Data may be tampered with.
• It makes the class difficult to maintain and vulnerable to bugs.
NB. The private data field cannot be accessed or modified unlike the public one which can be
accessed and modified.
Circle.h
#ifndef CIRCLE_H // Stands for if not defined
#define CIRCLE_H
class Circle{
private:
-9-
9. Objects and Classes
// The radius of the circle
double r; // The r variable cannot be accessed or modified
public:
// Construct a default circle object
Circle()
{
r = 1;
}
// Construct a circle object
Circle(double);
// A function that return the area of the circle
double getArea();
};
#endif
To make the private data field accessible, we provide get (accessor) function. To enable updating
of a private data field, we provide set (mutator) function.
Circle.h
#ifndef CIRCLE_H // Stands for if not defined
#define CIRCLE_H
class Circle{
private:
// The radius of the circle
double r; // The r variable cannot be accessed or modified
public:
// Construct a default circle object
Circle()
{
r = 1;
}
// Construct a circle object
Circle(double);
// Define a get function to return the private r variable
double getR()
{
return r;
}
- 10 -
9. Objects and Classes
// Define a set function to update the private r variable
void setR(double newR)
{
r = newR;
}
// A function that return the area of the circle
double getArea();
};
#endif
CLASS ABSTRACTION AND ENCAPSULATION:
Class abstraction is the separation of class implementation from the use of a class. Class
encapsulation is hiding the details of implementation through encapsulation. Class abstraction
and encapsulation are two sides of the same coin.
NB. The creator of a class provides a description of the class and lets the user know how it can be
used.
THE SCOPE OF VARIABLES:
The scope of instance and static variables is the entire class, regardless of where the variables are
declared. Global variables are declared outside all functions and are accessible to all functions
in its scope. The scope of a global variable starts from its declaration and continues to the end
of the program. Local variables are defined inside functions. The scope of a local variable starts
from its declaration and continues to the end of the block that contains the variable.
NB. The data fields are declared as variables and are accessible to all constructors and functions
in the class.
- 11 -
9. Objects and Classes
Representation Invariant:
The representation invariant is a condition that must be true over all valid instances of a class.
- 12 -
Python Classes
Python has a number of special method:
__init__ when invoked, it creates vals which is an object of type list. When a new object is
created, it is bound to the formal parameter self.
class InSet(object):
def __init__(self):
self.vals = []
__str__ is used to return a string when invoking the print() function to print the object.
class InSet(object):
def __init__(self):
self.vals = []
def __str__(self):
result = ""
for i in self.vals:
result = result + ", " + str(i)
return "{" + result[2:] + "}"
__it__ allows for the overloading of the less-than operator (<) for custom objects.
Class Variable vs Instance Variable:
class Circle(object):
pi = 3.14159 ## pi is a class variable
def __init__(self, r=1):
self.r = r ## r is an instance variable
def getR(self):
return self.r
def getArea(self):
return self.r * self.r * Circle.pi
- 13 -
Python Classes
def __str__(self):
return "Circle area is " + str(self.getArea())
Representation Invariant:
The representation invariant for IntSet is that vals contains no duplicates.
class InSet(object):
def __init__(self):
self.vals = []
def insert(self, e):
if e not in self.vals:
self.vals.append(e)
else:
return str(e) + " is already in the set"
def member(self, e):
return e in self.vals
def remove(self, e):
try:
self.vals.remove(e)
except:
raise ValueError(str(e) + " isn't in the set")
def getMembers(self):
return self.vals[:]
def __str__(self):
result = ""
self.vals.sort()
for e in self.vals:
result = result + str(e) + ', '
return '{' + result[:-2] + '}'
- 14 -
Python Classes
Inheritance:
Inheritance provides a convenient mechanism for building groups of related abstractions.
The subclass inherits the attributes (properties) of its superclass. In addition, the subclass can
override attributes of its superclass.
Circle.py
class Circle(object):
pi = 3.14159
def __init__(self, r=1):
self.r = r
def getR(self):
return self.r
def getArea(self):
return self.r * self.r * Circle.pi
def __str__(self):
return "Circle area is " + str(self.getArea())
Square.py
from Circle import Circle
class Square(Circle):
def __init__(self, r=1):
Circle.__init__(self, r)
def getArea(self): ## Override the function getArea()
return self.r * self.r
def __str__(self): ## Override the function __str__
return "Suqare area is " + str(self.getArea())
- 15 -
Python Classes
Information hiding:
To make the variable or the function private and invisible outside the class, put (__) before the
variable or the function but not after it.
class Circle(object):
)
__pi = 3.14159
## __pi is an invisible (private) class variable
## which cannot be accessed outside the class
def __init__(self, r=1):
self.r = r
def getR(self):
return self.r
def getArea(self):
return self.r * self.r * Circle.pi
def __str__(self):
return "Circle area is " + str(self.getArea())
NB. When a subclass attempts to use a hidden attribute of its superclass an AttributeError
occurs.
NB. It is not unusual during the creation and later maintenance of a program to go back and add
new classes or new attributes to old classes. Good programmers design their programs so as to
minimize the amount of code that might need to be changed when that is done.
Python built-in functions:
isinstance(instanceName, objectName) this returns True or False.
- 16 -