OOP2
OOP2
OOP2
2nd Level
2nd Course
s 4 i f b n . c o m
CHAPTER 14 s 4 i f b n .co m
14.1 Introduction
We came across the term overloading when we discussed function
overloading in Chapter 5 and constructor overloading in Chapter 11, the word
overloading means giving more than one job to something.
This chapter present a new OOP feature that apply overloading to the C++
language operators, to make the operator perform additional tasks beside the
built-in task it assigned to. Before we discuss operators overloading, we have
seen and worked in the previous chapters of this book with various types of
operators like arithmetic, comparison, logical, bitwise, addressing and other
operators, now let us organize these operators depending on their operands.
Operators
If the operator takes only one operand it is called unary operator, if the
operator takes two operands it is called binary operator, and if it takes three
operands it is called ternary operator.
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
For example:
Note that some operators can beave as unary and binary in defferent
functionality, for example the minus sign – is considered unary operator while
the subtraction sign – is binary operator.
Operators
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
Warning
The idea behind operators overloading is to make the operators that works on
simple data types also can work on objects, for example the increment
operator ++ is defined in the language to work on numbers, we can overload
this operator by adding additional functionality to it to make it work on objects
also as we will see in the upcoming section.
The member function simply increments the age data member by one when
called in the main function Line 36.
We can overload the increment operator and make it work with objects so
we can do this:
++s;
Instead of this:
s.incAge();
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
Program 14.1
1 // Student Class
2 #include<iostream>
3 using namespace std;
4 class student {
5 private:
6 string Name;
7 int ID, Age, Deg1, Deg2, Deg3;
8 public:
9 student(){
10 cout<<"Enter student ID: "; cin>>ID;
11 cout<<"Enter student Name: "; cin>>Name;
12 cout<<"Enter student Age: "; cin>>Age;
13 cout<<"Enter student Deg1: "; cin>>Deg1;
14 cout<<"Enter student Deg2: "; cin>>Deg2;
15 cout<<"Enter student Deg3: "; cin>>Deg3;
16 }
17
18 void incAge(){
19 Age++;
20 }
21
22 void print(){
23 cout<<"Student Name "<<Name<<endl;
24 cout<<"Student ID: "<<ID<<endl;
25 cout<<"Student Age: "<<Age<<endl;
26 cout<<"Student Deg1: "<<Deg1<<endl;
27 cout<<"Student Deg2: "<<Deg2<<endl;
28 cout<<"Student Deg3: "<<Deg3<<endl;
29 }
30 };
31
32 int main(){
33 student s;
34
35 s.incAge();
36 s.print();
37
38 return 0;
39 }
40
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
++s;
We need to add a special function inside the call we will name the function
++ preceded with the keyword operator, this function will be added:
We can rewrite Program 14.1 adding the unary ++ overloaded operator, see
Program 14.2, note the operator overloading function does not return a value
to the calling line so we need to give it void as a return type.
s++;
Note that the int added to the argument for the compiler to not confuse it with
the prefix increment operator, the argument list must be unique for each
function with the same name, remember this was a condition for function
overloading, so here we have overloaded function for operator overloading,
see the Program 14.3 both functions are added.
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
Program 14.2
1 // Unary Overloading
2 #include<iostream>
3 using namespace std;
4 class student {
5 private:
6 string Name;
7 int ID, Age, Deg1, Deg2, Deg3;
8 public:
9 student(){
10 cout<<"Enter student ID: "; cin>>ID;
11 cout<<"Enter student Name: "; cin>>Name;
12 cout<<"Enter student Age: "; cin>>Age;
13 cout<<"Enter student Deg1: "; cin>>Deg1;
14 cout<<"Enter student Deg2: "; cin>>Deg2;
15 cout<<"Enter student Deg3: "; cin>>Deg3;
16 }
17
18 void print(){
19 cout<<"Student Name "<<Name<<endl;
20 cout<<"Student ID: "<<ID<<endl;
21 cout<<"Student Age: "<<Age<<endl;
22 cout<<"Student Deg1: "<<Deg1<<endl;
23 cout<<"Student Deg2: "<<Deg2<<endl;
24 cout<<"Student Deg3: "<<Deg3<<endl; }
25
26 void operator ++(){
27 ++Age; }
28 };
29
30 int main(){
31 student s;
32 ++s;
33 s.print();
34
35 return 0;
36 }
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
We can apply the same steps above to overload the decrement operator in
both notations the prefix and the postfix.
Program 14.3
1 // Unary Overloading
2 #include<iostream>
3 using namespace std;
4 class student {
5 private:
6 string Name;
7 int ID, Age, Deg1, Deg2, Deg3;
8 public:
9 student(){
10 cout<<"Enter student ID: "; cin>>ID;
11 cout<<"Enter student Name: "; cin>>Name;
12 cout<<"Enter student Age: "; cin>>Age;
13 cout<<"Enter student Deg1: "; cin>>Deg1;
14 cout<<"Enter student Deg2: "; cin>>Deg2;
15 cout<<"Enter student Deg3: "; cin>>Deg3;
16 }
17 void print(){
18 cout<<"Student Name "<<Name<<endl;
19 cout<<"Student ID: "<<ID<<endl;
20 cout<<"Student Age: "<<Age<<endl;
21 cout<<"Student Deg1: "<<Deg1<<endl;
22 cout<<"Student Deg2: "<<Deg2<<endl;
23 cout<<"Student Deg3: "<<Deg3<<endl; }
24
25 void operator ++(){
26 ++Age; }
27
28 void operator ++(int){
29 Age++; }
30
31 };
32 int main(){
33 student s;
34 ++s; // s++ also do the same thing
35 s.print();
36
37 return 0;
38 }
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
Let’s take an example on adding two vectors, for simplicity let’s suppose a
vector has only a starting point with two coordinates so in order to add two
vectors we intend to add the corresponding coordinates to produce a new
vector that represent the summation of two vectors, so we will overload the +
operator.
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
Program 14.4
1 // Binary Overloading
2 #include<iostream>
3 using namespace std;
4 class vector {
5 private:
6 int x, y;
7 public:
8 vector(int a, int b){
9 x=a;
10 y=b;
11 }
12
13 void print(){
14 cout<<"X = "<<x<<" Y = "<<y<<endl;
15 }
16
17 vector operator +(vector v2){
18 vector v3(x + v2.x, y + v2.y);
19 return v3; }
20
21 };
22
23 int main(){
24 vector v1(1,2), v2(3,4);
25
26 v1.print();
27 v2.print();
28
29 vector v3 = v1 + v2;
30
31 v3.print();
32
33 return 0;
34 }
© S a i f B a sh ar 2021-2022
CHAPTER 14 s 4 i f b n .co m
Exercises 14
© S a i f B a sh ar 2021-2022
Chapter 15
Inheritance
15.1 Introduction
15.2 Single Inheritance
15.3 Multiple Inheritance
15.4 Hierarchical Inheritance
15.5 Multilevel Inheritance
15.6 Private, Public and Protected Inheritance
15.7 Overriding Methods
15.8 Virtual Functions
Exercises 15
s 4 i f b n . c o m
CHAPTER 15 s 4 i f b n .co m
15.1 Introduction
Another fundamental concept in object-oriented programming is the
concept of inheritance, it is considered the third pillar of OOP in addition to
encapsulation and polymorphism.
Inheritance also called code reuse, code reuse means that when we build a
class for a particular concept, we can use this class and inherit its functionality
solving some problem, this mechanism will save huge amount of time since we
can reuse classes already had been built without the need to rebuild them.
This chapter present a new OOP feature which is inheritance and illustrate the
basic types of inheritance and how to implement them in C++ language, but
before we start, we need to know some basic definitions.
Base class: it is the class that we want to reuse its code (data members,
member functions), also called parent class or superclass in java language.
Derived class: it is the class that is using the data and/or functionality of the
base class through inheritance, also called child class or sub class in java
language.
Inhritance
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
As we have seen in the previous chapters, classes are meant to represent the
real world we can represent anything in the world in classes, in inheritance the
base class can be thought of the more general class and the derived class is
the more specific class, to illustrate this idea let’s take an example from the
real world. If we wanted to represent a person in class and a student in another
class, we can represent them in separate classes each of which have its own
data members and member functions, but there are many data member that
are common in both classes, every person has a name, age, length, weight,
etc. also every student has a name, age, length, weight, etc. so instead of
redundantly writing these data in both classes we can write then once in the
base class and reuse them in the derived class.
Here we have the class person is the base class because it is the more general
concept, and the student class is considered the derived class because it is
the more specific concept. We can say every student is a person but not every
person is a student.
Program 15.1 implement both classes, not the base class person is written first
then the derived class student came second.
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Program 15.1
1 #include<iostream>
2 using namespace std;
3 class person {
4 private:
5 string name;
6 int age, length, weight;
7 public:
8 person(){
9 cout<<"Enter Name: "; cin>>name;
10 cout<<"Enter Age: "; cin>>age;
11 cout<<"Enter Length: "; cin>>length;
12 cout<<"Enter Weight: "; cin>>weight; }
13
14 void print(){
15 cout<<"Name: "<<name<<endl;
16 cout<<"Age: "<<age<<endl;
17 cout<<"Length: "<<length<<endl;
18 cout<<"Weight: "<<weight<<endl; }
19 };
20
21 class student : public person {
22 private:
23 int level;
24 float avg;
25 public:
26 student(){
27 cout<<"Enter Average: "; cin>>avg;
28 cout<<"Enter Level: "; cin>>level; }
29
30 void print(){
31 person::print();
32 cout<<"Average: "<<avg<<endl;
33 cout<<"Level: "<<level<<endl; }
34 };
35
36 int main(){
37 student s;
38
39 s.print();
40
41 return 0; }
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
This line mean connect the class student with the class person using the colon
operator ( : ) here the person class is the base class and the student class is the
derived class. The inheritance type is public more on this later.
Person
Student
Figure 15.2, Single Inheritance
Note that creating an object from the derived class will automatically trigger
the base class constructor then the derived class constructor.
If we want to send values in the derived class object’s definition take a look at
Program 15.2
Lines 26 and 27 the head of the student constructor will receive all the data
from the main function and pass the inherited data to the parent constructor
the person constructor, and take the values of level and avg to the student’s
data member
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Program 15.2
1 #include<iostream>
2 using namespace std;
3 class person {
4 private:
5 string name;
6 int age, length, weight;
7 public:
8 person(string n, int a, int len, int w){
9 name=n;
10 age=a;
11 length=len;
12 weight=w; }
13
14 void print(){
15 cout<<"Name: "<<name<<endl;
16 cout<<"Age: "<<age<<endl;
17 cout<<"Length: "<<length<<endl;
18 cout<<"Weight: "<<weight<<endl; }
19 };
20
21 class student : public person {
22 private:
23 int level;
24 float avg;
25 public:
26 student(string n, int a, int len, int w, float
27 v, int lev): person(n, a, len, w){
28 avg=v;
29 level=lev; }
30
31 void print(){
32 person::print();
33 cout<<"Average: "<<avg<<endl;
34 cout<<"Level: "<<level<<endl; }
35 };
36
37 int main(){
38 student s ("ali",20,170,75,95,2);
39 s.print();
40
41 return 0; }
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Important note: the inherited data from the base class cannot be accessed
directly in the derived class due to encapsulation, if we want to access these
data directly, we need to use the access specifier protected in the base
class, protected means the data will be private in both the base and the
derived classes.
The derived class will inherit the data members and member functions of both
base classes, let carry on the same previous example by adding another class
gradStudent that represent a graduate student, that will inherit from the person
and the student classes, see Program 15.3
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Program 15.3
1 #include<iostream>
2 using namespace std;
3 class person {
4 private:
5 string name;
6 int age;
7 public:
8 person(string n, int a){
9 name=n;
10 age=a; }
11
12 void print(){
13 cout<<"Name: "<<name<<endl;
14 cout<<"Age: "<<age<<endl;}
15 };
16
17 class student {
18 private:
19 int level;
20 float avg;
21 public:
22 student(float v, int lev){
23 avg=v;
24 level=lev; }
25
26 void print(){
27 cout<<"Average: "<<avg<<endl;
28 cout<<"Level: "<<level<<endl; }
29 };
30
31 class gradStudent: public person, public student
32 {
33 private:
34 string research;
35 public:
36 gradStudent(string n, int a, float v, int lev,
37 string r):person(n,a),student(v,lev)
38 {
39 research=r; }
40
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Lines 36 and 37 the derived class constructor invoke the parent classes
constructors and sending the appropriate data.
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Base Class
For example, id we have an Employee class with the data members (name,
age, salary) and we derive a class of Manager that will inherit all the data from
the employee class and has the data member (title as string), another derived
class Scientist also will inherit from the employee class with a data member of
its own (publication as string), the third class is Worker will inherit from the
employee class with no data of its own, the three classes are illustrated in
Figure 15.4
Employee
Program 15.4 implement the four classes with the appropriate inheritance
connections, and constructors’ callings.
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
The appropriate data are assigned to the classes data members and the base
class data are sent to the base class constructor from the derived classes
constructors.
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Program 15.4
1 #include<iostream>
2 using namespace std;
3 class Emp {
4 private:
5 string name;
6 int age, salary;
7 public:
8 Emp(string n, int a, int s){
9 name=n;
10 age=a;
11 salary=s; }
12
13 void print(){
14 cout<<"Name: "<<name<<endl;
15 cout<<"Age: "<<age<<endl;
16 cout<<"Salary: "<<salary<<endl;}
17 };
18
19 class Manager : public Emp{
20 private:
21 string title;
22 public:
23 Manager(string n, int a, int s, string t):
24 Emp(n, a, s){
25 title=t; }
26
27 void print(){
28 Emp::print();
29 cout<<"Title: "<<title<<endl; }
30 };
31
32 class Scientist: public Emp {
33 private:
34 string publication;
35 public:
36 Scientist(string n, int a, int s, string p):
37 Emp(n,a,s){
38 publication=p; }
39
40
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Base Class
Derived 1
Derived 2
Figure 15.5, Multilevel Inheritance
The derived 1 class will be a derived class from the base class and a base class
for the derived 2 class. The most general concept is considered a first level
base class, the next specific class is considered the base class for the more
specific class and so on. This process can be extended to any number of levels,
to illustrate the idea let’s take the following example:
Person
Employee
Manager
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Program 15.5
1 #include<iostream>
2 using namespace std;
3 class Person {
4 private:
5 string name;
6 int age;
7 public:
8 Person(string n, int a){
9 name=n;
10 age=a; }
11
12 void print(){
13 cout<<"Name: "<<name<<endl;
14 cout<<"Age: "<<age<<endl; }
15 };
16
17 class Emp : public Person{
18 private:
19 int salary;
20 public:
21 Emp(string n, int a, int s):Person(n,a){
22 salary=s; }
23
24 void print(){
25 Person::print();
26 cout<<"Salary: "<<salary<<endl; }
27 };
28
29 class Manager : public Emp{
30 private:
31 string title;
32 public:
33 Manager(string n, int a, int s, string t):
34 Emp(n, a, s){
35 title=t; }
36
37 void print(){
38 Emp::print();
39 cout<<"Title: "<<title<<endl; }
40 };
Base Class
Derived 1 Derived 2
Derived 3
Figure 15.6, Hybrid Inheritance
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Derived Class
Base Class Data Public Private Protected
Inheritance Inheritance Inheritance
• Private • No Access • No Access • No Access
• Protected • Protected • Private • Protected
• Public • Public • Private • Protected
For example, if the base class has public data and methods and the
inheritance specifier was private:
this means that the inherited data and methods will be private in the
derivedClass.
The answer is the method in the derived class will be executed, we say the
method in the derived class will override the inherited method that has the
same name. for example, see Program 15.6
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Program 15.6
1 #include<iostream>
2 using namespace std;
3 class A {
4 public:
5 void test(){
6 cout<<"this is a test from A class"<<endl;
7 }
8 };
9
10 class B : public A{
11 public:
12 void test(){
13 cout<<"this is a test from B class"<<endl;
14 }
15 };
16
17
18 int main(){
19
20 A Obj1;
21 Obj1.test();
22
23 B Obj2;
24 Obj2.test();
25
26 Obj2.A::test();
27
28 return 0;
29 }
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Program 15.6 Line 20, declare an object from the base class. Line 21 call the
member function of the base class (no inheritance here).
Line 23, declare an object from the derived class (which now has two test
methods). Line 24 call the test method of the derived class; the test method of
the derived class will override the test method in the base class.
Line 25, call the test method of the base class canceling the overriding
feature.
The benefit of the override feature is that we can customize the methods in
the base class without changing their code.
For example, if we have the following classes all of them have the area ()
method: (Program 15.7)
Shape
Square Cirlce
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Program 15.7
1 #include<iostream>
2 using namespace std;
3 class Shape {
4 public:
5 void area(){
6 cout<<"this is a shape area"<<endl;
7 }
8 };
9
10 class Square : public Shape{
11 public:
12 void area(){
13 cout<<"this is a square area"<<endl;
14 }
15 };
16
17 class Circle : public Shape{
18 public:
19 void area(){
20 cout<<"this is a circle area"<<endl;
21 }
22 };
23
24 int main(){
25
26 Square S;
27 Circle C;
28
29 Shape *Sh1 = &S;
30 Sh1->area();
31
32 Shape *Sh2 = &C;
33 Sh2->area();
34
35 return 0;
36 }
© S a i f B a sh ar 2021-2022
CHAPTER 15 s 4 i f b n .co m
Lines 26, define an object from the derived square class, Line 27 define an
object from the derived class circle.
Line 29, define a pointer to object of the base class that points to the square
object defined earlier, Line 30 calling the area method for this pointer to
object will invoke the area of the base class, the override feature now is
broken.
Line 32, define a pointer to object of the base class that points to the circle
object defined earlier, Line 33 calling the area method for this pointer to
object will invoke the area of the base class, the override feature now is
broken.
We use the virtual function in this situation to restore the override feature, so
the area method of the base class should be like this:
Virtual function: is an inheritable and overridable function or method for which dynamic
dispatch is facilitated. This concept is an important part of the (runtime) polymorphism a
virtual function defines a target function to be executed, but the target might not be known at
compile time.
Note that the virtual function if it was empty it is called pure virtual function
written like this
© S a i f B a sh ar 2021-2022
Chapter 16
Templates
16.1 Introduction
16.2 Function Template
16.3 Class Template
Exercises 16
s 4 i f b n . c o m
CHAPTER 16 s 4 i f b n .co m
16.1 Introduction
Templates are considered a useful technique in programming with C++,
it allows us to build programs that will work on multiple data types.
For example, if we have a program for the stack data structure (or any data
structure) we know that it has an array that will hold the items that we want to
push inside this stack, we have to define this array and specify a data type to
this array.
By specifying a fixed data type for this array, we can work only with a stack
that holds integers, if we wanted to work with a stack that holds characters,
we need to build another stack program for that.
Fortunately, there is another way that enable us to work with the stack with
any data type that we want by implementing only one program by using a
technique called templates.
Suppose you want to build a function that return the max number from two
numbers, you may code it like the following simple program 16.1:
© S a i f B a sh ar 2021-2022
CHAPTER 16 s 4 i f b n .co m
Program 16.1
1 #include<iostream>
2 using namespace std;
3
4 int maximum(int n1, int n2) {
5 if(n1 > n2)
6 return n1;
7 else
8 return n2;
9 }
10
11 int main(){
12
13 int number1, number2;
14 cout<<"Enter Two Numbers: ";
15 cin>>number1>>number2;
16
17 cout<<maximum(number1, number2) <<endl;
18
19 return 0;
20 }
Now what if you want to test two float numbers, or two doubles or even two
characters, you have to build a function for every data type.
There is a way by building only one function and it will work for any data type
that we give it using the template technique, see the following program 16.2
© S a i f B a sh ar 2021-2022
CHAPTER 16 s 4 i f b n .co m
1 #include<iostream>
2 using namespace std;
3
4 template <class T>
5
6 T maximum(T n1, T n2) {
7 if(n1 > n2)
8 return n1;
9 else
10 return n2;
11 }
12
13 int main(){
14
15 int number1, number2;
16 cout<<"Enter Two Numbers: ";
17 cin>>number1>>number2;
18
19 cout<< maximum(number1, number2)<<endl;
20
21 char char1, char2;
22 cout<<"Enter Two Characters: ";
23 cin>> char1>> char2;
24
25 cout<< maximum(char1, char2)<<endl;
26
27 float f1, f2;
28 cout<<"Enter Two Floats: ";
29 cin>> f1>> f2;
30
31 cout<< maximum(f1, f2)<<endl;
32
33 return 0;
34 }
35
36
37
38
39
40
© S a i f B a sh ar 2021-2022
CHAPTER 16 s 4 i f b n .co m
Note that in program 16.2 we built one function that can handle three
different data types, in Line 19 we sent two integers, in Line 25 we sent two
characters, in Line 31 we sent two floats.
We say that the function maximum is a template function that works on any
data type the we pass to it. The compiler will generate the function code for
the passed argument when the function is called.
Let’s take another example, for finding an element and return its index see
program 16.3
Program 16.3 illustrate the idea of function template by using a single function
to search arrays of different types.
Line 17 we passed an array of integers and an integer value to find its location
in the array
Line 23 we passed an array of floats and a float number to find its location in
the array
© S a i f B a sh ar 2021-2022
CHAPTER 16 s 4 i f b n .co m
1 #include<iostream>
2 using namespace std;
3
4 const int size = 5;
5 template <class S>
6
7 int find(S array[size], S element) {
8
9 for(int i=0; i<size; i++)
10 if(array[i]== element)
11 return i;
12 }
13
14 int main(){
15
16 int a[size] = {1, 2, 3, 4, 5};
17 cout<< find(a, 4)<<endl;
18
19 char c[size] = {'a', 'b', 'c', 'd', 'e'};
20 cout<< find(c, 'e')<<endl;
21
22 float f[size] = {1.3, 3.4, 6.5, 7.9, 8.5};
23 cout<< find(f, 1.3)<<endl;
24
25 return 0;
26 }
© S a i f B a sh ar 2021-2022
CHAPTER 16 s 4 i f b n .co m
© S a i f B a sh ar 2021-2022
CHAPTER 16 s 4 i f b n .co m
Note that we specified the type of the items array as a template variable also
the value in the push method’s argument and the return type of the pop
method.
And so on…
© S a i f B a sh ar 2021-2022