Title: Programming Principles II
1Programming Principles II
Andreas Savva
- Lecture Notes 6.1
- Object Oriented Programming
2Objects
- An object is simply a self-contained entity that
has an existence independent of other entities. - a pencil
- a book
- a car
- a basketball
- a watch
- a house
3Objects and Classes
- A class can be regarded as the general form of an
object - The Tower Bridge in London belongs to the class
of bridges - The Bran Castle (Draculas castle in Rumania)
belongs to the class of castles - Barack Obama belongs to the class of USA
presidents or to the class of humans - Lionel Messi belongs to the class of football
players - The Land Rover Defender 90 TDI 4WD with RegNo
CAA236 belongs to the class of cars
4Attributes and Operations
- Properties of the class Employ
- Attributes and operations are called members of a
class. - Attributes are called data members.
- Operations are called member functions.
Attributes Operations
Name Hire
Employee Number Promote
Job title Give pay rise
Salary Fire
Years of employment
5Abstract Data Types (ADT)
- Data cannot be accessed directly.
- Data can only be accessed indirectly via the
subprograms (member functions) associated with
the data. - Thus, the class contains
- The data structure.
- Subprograms to access and/or modify the data
structure.
6Information Hiding
- A client (user program) does not need to know how
the data are actually stored or how the methods
are programmed. This important programming
strategy is called information hiding. - Data members and member functions (methods)
available to a client are called public. - Private variables and member functions
(functions) may be used in the implementation of
the class, but are not available to a client. - Methods of a class are public
- Functions in a class are private
7Example Abstract Data Type
- Main activities for operating a car are
- steering, accelerating, braking
- The design of a car can be viewed as an ADT with
operations - steer, accelerate, brake
- Two cars may implement these operations in
different ways. - Most drivers can operate any car since the ADT
presents a uniform method of operation.
8C Class Declaration
- class Name
- public
- // Public members go here (internal to the
class) - private
- // Private members go here (visible from
outside)
9The Class Time
- class Time
- public
- void setTime(int, int, int)
- void print24hour()
- void print12hour()
- private
- void twoDigits(int)
- int hour
- int minute
- int second
10Member Functions
- void TimesetTime(int h, int m, int s)
-
- hour h minute m second s
-
- void Timeprint24hour()
-
- twoDigits(hour) cout ltlt
- twoDigits(minute) cout ltlt
- twoDigits(second) cout ltlt endl
-
- void Timeprint12hour()
-
- int h (hour 12 0 ? 12 hour 12)
- twoDigits(h) cout ltlt
- twoDigits(minute) cout ltlt
- twoDigits(second)
- if (hour lt 12) cout ltlt am ltlt endl
11Creating and Using Objects
- int main()
-
- Time t
- t.setTime(16,23,5)
- cout ltlt "The time in 24 hour format is "
- t.print24hour()
- cout ltlt "The time in 12 hour format is "
- t.print12hour()
- cout ltlt endl
- return 0
12Defining Functions in the Class
- class Time
- public
- void setTime(int h, int m, int s)
-
- hour h minute m second s
-
- void print24hour()
- void print12hour()
- private
- void twoDigits(int n)
-
- if (n lt 10) cout ltlt 0
- cout ltlt n
-
- int hour
- int minute
- int second
13Constant Member Functions
- In constant member functions we cannot change the
values of data members.
- class Time
- public
- void setTime(int, int, int)
- void print24hour() const
- void print12hour() const
- private
- void twoDigits(int) const
- int hour
- int minute
- int second
-
- void Timeprint12hour() const
-
- hour hour 12 // ERROR
14Mutable Data Members
- Mutable data members can change their values in
constant member functions.
- class Time
- public
- void setTime(int, int, int)
- void print24hour() const
- void print12hour() const
- private
- void twoDigits(int) const
- mutable int hour
- int minute
- int second
-
- void Timeprint12hour() const
-
- hour hour 12 // CORRECT
15The Class Team
- class Team
- public
- Team() // Constructor
- Team(char, int 0, int 0, int 0) //
Constructor - Team(const Team) // Constructor
- void Setname(char)
- void Print() const
- void GamePlayed(int, int)
- Team() // Destructor
- private
- int Points() const
- char name20
- int wins
- int draws
- int losses
16Member Functions
- void TeamSetname(char s)
-
- strcpy(name, s)
-
- void TeamGamePlayed(int teamGoals, int
opponentsGoals) -
- if (teamGoals gt opponentsGoals) wins
- else if (teamGoals opponentsGoals) draws
- else losses
-
- void TeamPrint() const
-
- cout ltlt name ltlt " " ltlt Points() ltlt endl
-
- int TeamPoints() const
-
17Constructors
- Special functions have the name of the class
- Called automatically when an object of the class
is instantiated - Do not return a value (no return type is
specified) - Their purpose is to initialize the objects
attributes
TeamTeam() strcpy(name, "") wins 0
draws 0 losses 0
18Creating and Using Objects
- int main()
-
- Team ManUtd, Liv
- ManUtd.Setname(Manchester United)
- Liv.Setname(Liverpool FC)
- ManUtd.GamePlayed(3, 2)
- Liv.GamePlayed(2, 2)
- ManUtd.Print()
- Liv.Print()
- return 0
19Overloading the Constructor
- class Team
- public
- Team()
- Team(char , int 0, int 0, int 0)
- . . . . .
- private
- . . . . .
-
- TeamTeam()
-
- strcpy(name, "")
- wins 0
- draws 0
- losses 0
-
- TeamTeam(char s, int w, int d, int l)
-
Default values
20Objects
- int main()
-
- Team ManUtd(Manchester United, 3, 2, 1)
- ManUtd.Print()
- Team Liv(Liverpool FC, 2)
- Liv.GamePlayed(2, 2)
- Liv.Print()
- Team Arsenal Liv
- Arsenal.Setname(Arsenal FC)
- Arsenal.Print()
- Team RMadrid new Team(Real Madrid, 7, 1)
- RMadrid-gtPrint()
- return 0
21The Copy Constructor
- class Team
- public
- Team()
- Team(char, int 0, int 0, int 0)
- Team(const Team)
- . . . . .
- private
- . . . . .
-
- TeamTeam(const Team tm)
- strcpy(name, tm.name)
- wins tm.wins
- draws tm.draws
- losses tm.losses
-
- int main()
- Team Barcelona(Barselona FC, 8)
22The Destructor
- Functions that are called whenever an object is
deleted (e.g. goes out of scope) - Its purpose is to perform any necessary cleanup
operations - Has no return type
- Does not return a value
- class Team
- public
- . . . . .
- Team()
- private
- . . . . .
-
- TeamTeam()
-
- cout ltlt name ltlt is deleted\n
23Objects and Destructor
- int main()
-
- Team ManUtd(Manchester United, 3, 2, 1)
- Team Liv(Liverpool FC, 2)
- Team RMadrid new Team(Real Madrid, 7, 1)
- delete RMadrid
- Team Cyprus2
- Cyprus0.Setname(Omonoia)
- Cyprus1.Setname(APOEL)
- return 0
24The Initializer List
- C provides an alternative method of
initialization, called initializer list.
TeamTeam(char s, int w, int d, int l)
wins(w), draws(d), losses(l) // initializer list
strcpy(name, s) // cannot specify
initializer for arrays
25Pointers in Classes
- If a class object comes into existence
dynamically using the new operator, the
destructor must be called when this object is
destroyed using the delete operator. If a class
object comes into existence because it is a local
variable in a function, the destructor will be
called when the function returns.
class Vect public Vect(int size 5)
vectSize size theVect new intsize
// . . . Vect() delete
theVect private int vectSize int
theVect
26The Assignment statement
Vect a(10) // a is a vector of size
10 Vect b // c is a vector of default size
5 b a // assign a to b (DANGER) // the
destructor for b will be executed . . . . .
? ? ? ? ? ? ? ? ? ?
0 1 2 3 4 5 6 7 8 9
10
? ? ? ? ?
0 1 2 3 4
27Copy Constructor Assignment Operator
VectVect(const Vect a) vectSize
a.vectSize theVect new intvectSize
for (int i0iltvectSizei) theVecti
a.theVecti Vect Vectoperator(const Vect
a) if (this ! a) delete
theVect vectSize a.vectSize
theVect new intvectSize for (int
i0iltvectSizei) theVecti
a.theVecti return this
- The assignment operator deletes the existing
array storage, allocates a new array of the
proper size, and copies the elements into this
array. The if-statement checks against the
possibility of self assignment (a a). This is
done using the this keyword. For any class
object, this is a pointer to the address of the
object.
28The Class
class Vect public Vect(int size 5)
vectSize size theVect new intsize
// . . . Vect() delete
theVect Vect(const Vect) Vect
operator(const Vect) private int
vectSize int theVect
29The String Example
- class String
- public
- String(int 20)
- String(char)
- void Display()
- String()
- private
- int len
- char s
-
- StringString(int n)
- len n
- s new charn
- s0 '\0'
-
- StringString (char str)
- len strlen(str) 1
30Classes Vs. Structs
class Default is private
struct Default is public
- class Time
- public
- int hour
- int minute
- int second
- Time()
- Time(int, int, int)
-
- TimeTime()
- hour minute second 0
-
- TimeTime(int h, int m, int s)
- hour h
- minute m
- second s
struct Time int hour int minute int
second Time() Time(int, int,
int) TimeTime() hour minute
second 0 TimeTime(int h, int m, int s)
hour h minute m second s
31Overloading Operators
- C allows operators overloading, such as , ,
, and ltlt. The definition is similar to a
function, but in place of a function name we use
operator. In general, the is replaced by
the operator to be defined. For binary operators
we have two arguments, and for unary operators we
have just one.
struct ComplexNum ComplexNum(float r, float i)
real r imaginary i . . . . . friend
bool operator(const ComplexNum, const
ComplexNum) private float real float
imaginary bool operator(const ComplexNum
a, const ComplexNum b) return a.real
b.real a.imaginary b.imaginary void
main() ComplexNum N1(3, 12) // 3 12i
ComplexNum N2(-2, 1) // -2 i cout ltlt
(N1N2) // output 0 (false)
32Overloading Operators
- Another useful application is defining input and
output operators for classes and structures. Here
is how to define an output operator for the
ComplexNum structure. The type ostream is the
systems output structure. The standard output,
cout is of this type.
struct ComplexNum ComplexNum(float r, float i)
real r imaginary i . . . . . friend
bool operator(const ComplexNum, const
ComplexNum) friend ostream operatorltlt(ostream
, const ComplexNum ) private float
real float imaginary ostream
operatorltlt(ostream out, const ComplexNum a)
out ltlt a.real ltlt (a.imaginarygt0 ? -) ltlt
fabs(a.imaginary) ltlt i return out void
main() ComplexNum N1(3, 12) cout ltlt
N1 // output 312i
33Matrix OperationsA complete program
include ltiostreamgt using namespace std const
int MAX 10 enum Error_code fail,
success class Matrix public Matrix()
void ReadMatrix() void DisplayMatrix()
const Error_code AddSubtract(char , const
Matrix, const Matrix) Error_code
Multiply(const Matrix, const Matrix) private
int row, col float entryMAXMAX
34Constructor ReadMatrix
MatrixMatrix() row col 0 void
MatrixReadMatrix() cout ltlt Enter number
of rows and colums cin gtgt row gtgt col
if (row gt MAX col gt MAX) row col
0 else cout ltlt Enter the ltlt
row ltlt x ltlt col ltlt matrix elements\n
for (int i 0 i lt row i) for
(int j 0 j lt col j) cin gtgt
entryij cout ltlt endl
35DisplayMatrix AddSubtract
void MatrixDisplayMatrix() const for (int
i 0 i lt row i) for (int j 0 j
lt col j) cout ltlt setw(8) ltlt fixed
ltlt setprecision(2) ltlt entryij cout
ltlt endl cout ltlt endl ltlt
endl Error_code MatrixAddSubtract(char c,
const Matrix A, const Matrix B) if (A.row
! B.row A.col ! B.col) return fail row
A.row col A.col for (int i 0 i lt
row i) for (int j 0 j lt col j)
switch (c) case
entryij A.entryij B.entryij
break case entryij
A.entryij B.entryij break
default return fail
return success
36Multiply
Error_code MatrixMultiply(const Matrix A,
const Matrix B) if (A.col ! B.row) return
fail row A.row col B.col for
(int i 0 i lt row i) for (int j 0
j lt col j) entryij
0.0 for (int k 0 k lt A.col
k) entryij
A.entryik B.entrykj
return success
37The main()
void main() int choice do
cout ltlt Enter 1 for addition, 2 for subtraction,
3 for multiplication cin gtgt choice
while (choice lt 1 choice gt 3) Matrix
A, B, Result A.ReadMatrix()
B.ReadMatrix() Error_code outcome
switch (choice) case 1 outcome
Result.AddSubtract(, A, B) break
case 2 outcome Result.AddSubtract(, A, B)
break case 3 outcome
Result.Multiply(A, B) break if
(outcome fail) cout ltlt \nMatrices are not
compatible\n else cout ltlt
\nResult\n\n ltlt flush
Result.DisplayMatrix()
38Programming Principles II
Andreas Savva
- Lecture Notes 6.2
- Inheritance
39Inheritance
- In a hierarchy of classes, the classes towards
the top are known as base classes or super
classes. Those further down are the derived
classes or sub-classes. - Derived classes are specialisations of base
classes, sharing their properties but adding
their own.
40Inheritance in C
- In object-oriented languages we can use classes
that are already declared as base classes and
derive specializations from them.
class Today public Today() void
setDate(int, int, int) void Tomorrow() void
displayDate() const protected int day int
month int year private char
day_str15 char month_str15
class Calendarpublic Today public Calendar()
void AddBirthday() void DeleteBirthday() voi
d printTodayBirthday() const void displayDate()
const private int birthdaySize366 char
birthday3661030
41Derived Classes
class Today
class Calendar
methods Today (constructor) setDate
Tomorrow displayDate data members day
month year day_str month_str
methods Calendar (constructor) setDate
Tomorrow AddBirthday DeleteBirthday
printTodayBirthday displayDate data members
day month year birthdaySize birthday
Base class
Derived class
42Public Inheritance
class Today public Today(int, int,
int) void setDate(int, int, int) void
Tomorrow() void displayDate()
const protected int day int month int
year private char day_str15 char
month_str15
class Calendarpublic Today public Calendar(in
t, int, int) void AddBirthday() void
DeleteBirthday() void printTodayBirthday()
const void displayDate() const private int
birthdaySize366 char birthday3661030
class Calendar
Public Protected Private
Calendar day birthdaySize
setDate month birthday
Tomorrow year
AddBirthday
DeleteBirthday
printTodayBirthday
displayDate
43Protected Inheritance
class Today public Today(int, int,
int) void setDate(int, int, int) void
Tomorrow() void displayDate()
const protected int day int month int
year private char day_str15 char
month_str15
class Calendarprotected Today public Calendar
(int, int, int) void AddBirthday() void
DeleteBirthday() void printTodayBirthday()
const void displayDate() const private int
birthdaySize366 char birthday3661030
class Calendar
Public Protected Private
Calendar setDate birthdaySize
AddBirthday Tomorrow birthday
DeleteBirthday day
printTodayBirthday month
displayDate year
44Private Inheritance
class Today public Today(int, int,
int) void setDate(int, int, int) void
Tomorrow() void displayDate()
const protected int day int month int
year private char day_str15 char
month_str15
class Calendarprivate Today public Calendar(i
nt, int, int) void AddBirthday() void
DeleteBirthday() void printTodayBirthday()
const void displayDate() const private int
birthdaySize366 char birthday3661030
class Calendar
Public Protected Private
Calendar setDate
AddBirthday Tomorrow
DeleteBirthday day
printTodayBirthday month
displayDate year
birthdaySize
birthday
45Calling the base class constructorfrom the
derived class
- The constructor Today (with parameter values from
the parameters of Calendar) is invoked by placing
it in a member initialization list.
CalendarCalendar(int d, int m, int y)
Today(d, m, y) for (int i0 ilt366 i)
birthdaySizei 0
- If there has been a base class that requires no
parameters, then the compiler would ensure that
it would be called automatically, before the
derived class constructor. - However, even if no parameters are required, it
does not harm to invoke the base class
constructor explicitly, as above.
46Base class
enum hourType unknown, format12,
format24 class Time public Time(int, int,
int) void DisplayTime() const protected int
hour, min, sec hourType hour_type TimeTim
e(int h, int m, int s) hour(h), min(m), sec(s)
hour_type unknown void
TimeDisplayTime() const cout ltlt hour ltlt \n
ltlt min ltlt \n ltlt sec ltlt endl
47Derived classes
class Time24public Time public Time24(int,
int, int) void DisplayTime() const Time24
Time24(int h, int m, int s) Time(h, m, s)
hour_type format24 void
Time24DisplayTime() const cout ltlt hour ltlt
ltlt min ltlt ltlt sec ltlt endl class
Time12public Time public Time12(int, int,
int) void DisplayTime() const Time12Time1
2(int h, int m, int s) Time(h, m, s)
hour_type format12 void
Time12DisplayTime() const int h (hour 12
0 ? 12 hour 12) cout ltlt h ltlt ltlt min
ltlt ltlt sec cout ltlt (hour lt 12 ? am
pm) ltlt endl
48Objects of Derived classes
int main() Time24 t1(15, 29, 30) Time12
t2(22, 30, 45) t1.DisplayTime() t2.DisplayTim
e() return 0
49Arrays of Mixed Object Types
- The problem with arrays is that each of its
members must be of the same type. - However, we can declare an array of pointers to
the base class and assign objects of deferent
derived classes to it.
int main() Time t2 t0 new Time24(15,
29, 30) t1 new Time12(22, 30,
45) t0-gtDisplayTime() t1-gtDisplayTime()
return 0
- It must be noted however that the function
DisplayTime executed is the one belonging to the
base class.
50Polymorphism
- Polymorphism means having many shapes and it
refers to the ability to use the same name to
perform different functions in different classes. - One form of polymorphism is overloading
functions. - Another one is by using virtual functions in the
base classes.
class Time public Time(int, int,
int) virtual void DisplayTime()
const protected int hour, min, sec hourType
hour_type TimeTime(int h, int m, int s)
hour(h), min(m), sec(s) hour_type
unknown void TimeDisplayTime()
const cout ltlt hour ltlt \n ltlt min ltlt \n ltlt
sec ltlt endl
51Virtual Functions
- One of the key features of derived classes is
that a pointer to a derived class is
type-compatible with a pointer to its base class. - With non-virtual functions the compiler contains
a specific reference to the function (static
binding). - With virtual functions the compiler produces code
that will invoke the correct function for the
object that is being referred to while the
program is running (dynamic binding).
int main() Time t3 t0 new Time(8, 16,
12) t1 new Time24(15, 29, 30) t2 new
Time12(22, 30, 45) t0-gtDisplayTime() //
from base class Time t1-gtDisplayTime() //
from derived class Time24 t2-gtDisplayTime()
// from derived class Time12 delete t return
0
52Abstract Base Classes and Pure Virtual Functions
- An abstract base class is a class that has at
least one pure virtual function. - A pure virtual function is defined by appending
0 to the function declaration and has no
function definition.
class Time public Time(int, int,
int) virtual void DisplayTime() const
0 protected int hour, min, sec hourType
hour_type TimeTime(int h, int m, int s)
hour(h), min(m), sec(s) hour_type
unknown // DisplayTime() cannot be defined
53Abstract Base Classes
- The main difference between an abstract base
class and a regular polymorphic class is that,
because in abstract base classes at least one of
its members lacks implementation, instances
(objects) of that class cannot be created, i.e.
?
Time t
- int main()
-
- Time24 t24(15, 29, 30)
- Time12 t12(22, 30, 45)
- Time time1 t24
- Time time2 t12
- time1-gtDisplayTime() // from derived class
Time24 - time2-gtDisplayTime() // from derived class
Time12 - return 0
54Class Friends and Class Members
- Complex data structures typically involve the
interaction of many different classes. - Private members of a class may only be accessed
from within the class, but also from a friend (a
function or another class).
class Matrix // Matrix prototype Not
necessary class Vector // a 3-element
vector public . . . . . friend class
Matrix // allow Matrix access to coord
friend ostream operatorltlt(ostream, const
Vector) private double coord3 class
Matrix // a 3x3 array public .
. . . . Vector multiplyBy(const Vector v)
// multiply (a v) Vector w(0,0,0)
for (int i0ilt3i) for (int
j0jlt3j) w.coordi aij
v.coordj return w private
double a33
Vector is a friend of Matrix but Matrix is not a
friend of Vector
The output operator can now access the private
member data
55Functions Friends to Classes
class team public . . . . . friend int
main() // allow main() to access data
members private int wins, draws,
losses int main() team Liverpool(5,2,1)
int points 3 Liverpool.wins
Liverpool.draws cout ltlt Liverpool has ltlt
points ltlt points return 0
56Nesting Classes and Types within Classes
- A class definition can be nested within another
class. - In the example below only the Complex class can
use the Node class. We can also embed other sorts
of user-defined entities inside the class
definition, such as enumerations, structures, and
typedefs.
class Complex private class Node //
. . . (Node definition here) // . . .
(Remainder of complex definition)
57Class Templates
- Classes can have members that use template
parameters as types.
template ltclass Tgt class myPair T
values2 public myPair(T first, T second)
values0 first
values1 second
myPairltintgt A(123, 62) myPairltfloatgt B(3.0,
2.34)
58Member Functions Outside
- In case member functions are defined outside the
declaration of the class template, they must
always precede their definition with the template
ltgt prefix.
- template ltclass Tgt
- myPairltTgtmyPair(T first, T second)
-
- a first b second
-
- template ltclass Tgt
- T myPairltTgtGetMax()
-
- T result
- result agtb? a b
- return result
-
template ltclass Tgt class myPair T a,
b public myPair(T, T) T GetMax()
59Classes as Formal Parameters
- template ltclass Tgt
- class myPair
- T a, b
- public
- myPair(T first, T second) afirst
bsecond - bool Same(myPair) const
-
- template ltclass Tgt
- bool myPairltTgtSame(myPairltTgt original) const
-
- return a original.a boriginal.b
-
60Classes in Classes with Templates
template ltclass Wgt class Vector W
point3 template ltclassgt friend class
Vertices public Vector()point00point1
0point20 . . . template ltclass Tgt
class Vertices VectorltTgt curve100 public
. . . void print() for (int
i0ilt100 i) for (int d0 dlt3
d) cout ltlt curvei.pointd ltlt
'\t' cout ltlt endl
61Template Specialization
- A different implementation to a template can be
defined when a specific type is passed as a
template parameter. To do this a specialization
of that template must be declared.
Class template
template ltclass Tgt class myContainer
... template ltgt class myContainer ltchargt ...
Class template specialization
- When specializations for a template class are
declared, all its members, even those exactly the
same to the generic template class, must be
defined. The reason to this is that there is no
inheritance of members from the generic
template to the specialization.
62Template Specialization - Example
template ltclass Tgt class myContainer T
element public myContainer(T arg)element
arg T increase() return element) temp
late ltgt class myContainer ltchargt char
element public myContainer(char arg)element
arg char uppercase() if
(elementgta elsementltz) element
A a return element
Different implementation for characters
63Template Specialization - Example
int main() myContainerltintgt myint(12)
myContainerltchargt mychar(d) cout ltlt
myint.increase() ltlt endl cout ltlt
mychar.uppercase() ltlt endl return 0
64Non-Type parameters for Templates
- Besides the template arguments that are preceded
by the keywords class or typename which
represent types, templates can also have regular
parameters, similar to those found in functions.
template ltclass T, int Ngt class mySequence T
elementsN public void setElement(int n, T
value) T getElement(int x) template
ltclass T, int Ngt void mySequenceltT,NgtsetElement(
int x, T value) elementsx
value template ltclass T, int Ngt T
mySequenceltT,NgtgetElement(int x) return
elementsx
65Non-Type parameters for Templates
int main() mySequenceltint,5gt myints
mySequenceltdouble,8gt myreals
myints.setElement(0, 87) myreals.setElement(3,
3.14159) cout ltlt myints.getElement(0) ltlt
endl cout ltlt myreals.getElement(3) ltlt endl
return 0