0% found this document useful (0 votes)
11 views

Notes_CSE2001_OOP_with_C++_Unit III

The document covers Object Oriented Programming concepts in C++ focusing on Polymorphism and Inheritance. It explains compile-time and runtime polymorphism, including function and operator overloading, as well as various types of inheritance such as single, multiple, and multilevel inheritance. The learning objectives include understanding these concepts, demonstrating their implementations, and discussing access specifications and the use of abstract classes.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Notes_CSE2001_OOP_with_C++_Unit III

The document covers Object Oriented Programming concepts in C++ focusing on Polymorphism and Inheritance. It explains compile-time and runtime polymorphism, including function and operator overloading, as well as various types of inheritance such as single, multiple, and multilevel inheritance. The learning objectives include understanding these concepts, demonstrating their implementations, and discussing access specifications and the use of abstract classes.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

Class Notes: Object Oriented Programming with C++ (CSE2001)

UNIT – III

Syllabus:

Polymorphism and Inheritance:

Polymorphism, compile time polymorphism: function overloading, Operator overloading.


Inheritance - types of inheritance, constructors and destructors in inheritance, constraints
of multiple inheritance, Abstract base class – pure virtual functions, Run time
polymorphism - function overriding.

Learning Objectives: To

• Understand and discuss Polymorphism and its types.


• Demonstrate the compile time polymorphism using function overloading
and operator overloading.
• Understand and discuss the concept of inheritance and its types
• Demonstrate the concept of Inheritance
• Elaborate and demonstrate the concept of access specification.
• Understand the constructor and destructor calling in C++ inheritance
• Demonstrate the constructor and destructor calling in C++ inheritance.
• Understand the constraints / problem of multiple inheritance
• Demonstrate the Diamond problem of hybrid / multiple Inheritance.
• Intricate the concept and use of Abstract class.
• Elaborate the pure virtual function.
• Demonstrate the utilization of abstract class.
• Understand and discuss the Runtime polymorphism and function
overriding.
• Demonstrate runtime polymorphism through function overriding.

1. Polymorphism:

Refer programs polymorphism1.cpp, polymorphism2.cpp and


polymorphism3.cpp

Polymorphism is one of the four pillars of object-oriented programming.


Polymorphism means having many forms. It can be defined as the technique by
which an object / method can take many forms depending on the situation.

In programming terms, we can say that an object / method can behave


differently in different conditions.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Similarly in programming world also, we can have an operator “+” that is the
binary addition operator which behaves differently when the operands change.
For Example, when both the operands are numeric, it performs addition.

On the other hand, when the operands are string, it acts as concatenation
operator. Thus polymorphism, in a nutshell, means an entity taking up many
forms or behaving differently under different conditions.

Types of Polymorphism

o Compile time polymorphism


o Runtime polymorphism

The diagram to represent types and examples are shown below:

As shown in the above diagram, polymorphism is divided into compile-time


polymorphism and runtime polymorphism. Compile time polymorphism is
further divided into operator overloading and function overloading. Runtime
polymorphism is further implemented using virtual functions.

Compile time polymorphism is also known as early binding or static


polymorphism. In this type of polymorphism, object’s method is invoked at the
compile time. In the case of runtime polymorphism, the object’s method is
invoked at run time.

Runtime polymorphism is also known as dynamic or late binding or dynamic


polymorphism. We will look into the detailed implementation of each of these
techniques in our following topics.

Compile Time Polymorphism Vs. Run-Time Polymorphism

Let us see the main differences between compile time and runtime
polymorphism below.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Compile time polymorphism Runtime polymorphism

Also known as static polymorphism or Also known as dynamic polymorphism or


early binding late/dynamic binding

Objects method is invoked at compile time Object’s method is invoked at run time

Usually implemented using operator Implemented using virtual functions and


overloading and function overloading method overriding

Method Overloading is a compile-time Method overriding is runtime


polymorphism in which more than one polymorphism where more than one
method can have the same name but method has the same name with the same
different parameter list and types. prototype

Since methods are known at compile time, Execution is slower since the method is
execution is faster known at runtime

Provide less flexibility to implement Far more flexible for implementing


solutions since everything needs to be complex solutions as methods are decided
known at compile time at runtime

Compile Time Polymorphism

Compile time polymorphism is a technique in which an object’s method is invoked at


the compile time.

This type of Polymorphism is implemented in two ways.

o Function overloading
o Operator overloading

Function Overloading

A function is said to be overloaded when we have more than one function with the same
name but different parameter types or a different number of arguments.

Thus a function can be overloaded based on the parameter types, the order of
parameters and the number of parameters.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Note that two functions having the same name and same parameter list but different
return type is not an overloaded function and will result in a compilation error if used in
the program.

Similarly, when function parameters differ only in pointer and if array type is
equivalent, then it should not be used for overloading.

Other types like static and non-static, const and volatile, etc. Or parameter declarations
that differ in presence or absence of default values are also not to be used for
overloading as they are equivalent from the implementation point of view.

For Example (refer program: polymorphism2.cpp), the following function prototypes


are overloaded functions.

o Add(int,int);
o Add(int,float);
o Add(float,int);
o Add(int,int,int);

In the above program, we have a Summation class that defined three overloaded
functions named Add which takes two integer arguments, three integer arguments, and
two string arguments.
In the main function, we make four function calls that provide various parameters. The
first two function calls are straightforward. In the third function call to Add, we provide
two floating point values as arguments.
In this case, the function that is matched is int Add (int, int) as internally, the float is
converted to double and then matched with the function with the int parameters. If we
had specified double instead of float, then we would have another overloaded function
with double as parameters.
The last function call uses string values as parameters. In this case, the Add (+) operator
acts as a concatenation operator and concatenates the two string values to produce a
single string.

Benefits of Function Overloading


The main benefit of function overloading is that it promotes code reusability. We can
have as many functions as possible with the same name as long as they are overloaded
based on the argument type, argument sequence and the number of arguments.
By doing this it becomes easier to have different functions with the same name to
represent the behavior of the same operation in different conditions.
If function overloading was not present, then we would have had to write too many
different kinds of functions with different names, thus rendering the code unreadable
and difficult to adapt.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Operator Overloading
Operator overloading is the technique using which we give a different meaning to the
existing operators in C++. In other words, we overload the operators to give a special
meaning to the user-defined data types as objects.
Most of the operators in C++ are overloaded or given special meaning so that they can
work on user-defined data types. Note that while overloading, the basic operation of
operators is not altered. Overloading just gives the operator an additional meaning by
keeping their basic semantic same.

Though most of the operators can be overloaded in C++, there are some operators
which cannot be overloaded.

These operators are listed in the table below.

o Scope resolution operator(::)


o sizeof
o member selector(.)
o member pointer selector(*)
o ternary operator(?:)

The functions that we use to overload operators are called “Operator functions”.

Operator functions are similar to the normal functions but with a difference. The
difference is that the name of the operator functions begins with the keyword
“operator” followed by the operator symbol that is to be overloaded.

The operator function is then called when the corresponding operator is used in the
program. These operator functions can be the member functions or global methods or
even a friend function.

The general syntax of the operator function is:

return_type classname::operator op(parameter list)


{
//function body
}
Here “operator op” is the operator function where the operator is the keyword and op is
the operator to be overloaded. Return_type is the value type to be returned.

Overloading of the unary operator using member operator function.

o Refer programs opoverload1.cpp and opoverload4.cpp

Overloading of the binary operator using member operator function.


Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
o Refer programs opoverload2.cpp

Overloading of the binary operator using friend function.

o Refer programs opoverfriend.cpp

The only difference in the implementation is the use of friend function to overload the +
operator instead of a member function in the previous example.

o When friend function is used for a binary operator, we have to explicitly specify
both the operands to the function. Similarly, when the unary operator is
overloaded using friend function, we need to provide the single operand to the
function.

Operator Overloading Rules:

While performing operator overloading, we need to watch out the below rules.

o In C++, we are able to overload the existing operators only. Newly added
operators cannot be overloaded.
o When operators are overloaded, we need to ensure that at least one of the
operands is of the user-defined type.
o To overload certain operators, we can make use of friend function as well.
o When we overload unary operators using a member function, it doesn’t take any
explicit arguments. It takes one explicit argument when the unary operator is
overloaded using friend function.
o Similarly, when binary operators are overloaded using member function, we
have to provide one explicit argument to the function. When binary operators
are overloaded using friend function, the function takes two arguments.
o There are two operators in C++ that are already overloaded. These are “=” and
“&”. Therefore to copy an object of the same class, we need not overload the =
operator, and we can use it directly.

Advantages of Operator Overloading:

Operator overloading in C++ allows us to extend the functionality of operators to the


user-defined types including class objects in addition to the built-in types.

By extending the operator functionality to the user-defined types, we need not write
complex code to perform various operations on user-defined types but, we can do it in
one operation itself just like the built-in types.

Conclusion

Compile time polymorphism provides overloading facility mainly to extend the


functionality of the code in terms of function overloading and operator overloading.
o Function overloading makes the code simple and easily readable.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
o Operator overloading, can extend the functionality of operators, so that we can
do basic operations on user-defined types as well.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Runtime Polymorphism

Shortly, we will discuss Runtime Polymorphism

2. Inheritance

Inheritance is the process by which objects of one class can acquire the properties,
functions, and data of objects of another class. It follows the concept of hierarchical
classification. For example, the bird ‘sparrow’ is a part of the class ‘flying bird’ which is
again a part of the class ‘bird’. With the help of this sort of division each derived class
shares common characteristics and data with the class from which it is inherited.
Inheritance provides the idea of reusability. This means that we can add additional
features to an existing class without modifying or making any changes in it. This is
possible by deriving a new class from the existing class. The new class will acquire the
combined features of both parent and child class.

The real use of the inheritance is that it allows the programmer to reuse a class that is
almost, but not exactly, what he wants, and to alter the class and make changes in such a
way that it does not introduce any undesirable side-effects into the rest of the classes.
Note that each sub-class defines only those features that are unique to it and the rest of
it, it derives from its parent class. Without the use of any classification, each class would
have to explicitly include all of its features which would have taken a lot of time and
effort.

What is Inheritance in C++

Inheritance is one of the most powerful and widely used concepts in C++ or any other
Object-oriented language. Understanding this concept requires a little knowledge of
classes and objects. Using Inheritance, we can create a class that consists of general
methods and attributes. This class can be inherited by other classes containing more
specific methods.

By doing this we don’t have to write the same functionalities again and again which
saves time and increases the readability of code.

Syntax:
class derived_class: access_type base_class
{
// class body
};
Base class: The class which consists of all the general methods and attributes which can
be shared by other classes to increase code readability is called a base class.

Derived class: The class which consists of more specific methods and inherits a class is
called a derived class. A derived class can also be a base class for some other derived
class.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
If we create a class XYZ (College), with some attributes and methods. Now a class
student will have some other attributes, but it will also include the elements of XYZ class
and the same goes for a faculty class. Let’s see a diagram:

So, the student and faculty class will inherit from XYZ.

Access specifier - We understood how a class can inherit another class. But some
people might say that it is an unsafe method as all the attributes and methods of the
base class or the parent class is shared with the child class or the derived class. For
example, if a class ‘Bank’ is inherited by the class ‘customers’ and ‘investors’. Attributes
of class ‘Bank’ such as ‘vaultpassword’, other customer-related information and private
data is shared with the ‘customers’ and the ‘investors’ class which is unsafe.

To solve the above problem C++ uses access specifiers to limit the access of base class
attributes to the derived class. There are a total of 3 types of access specifiers in C++
• Public
• Private
• Protected
The below table will give you a good understanding of what type of data can be accessed
by derived class according to different access specifiers.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Types of Inheritance:

Refer programs: inheritancesingle.cpp, inheritancesingle1.cpp,


inheritanceaccess.cpp, inheritancemultilevel.cpp, inheritancemultiple.cpp,
inheritancehybrid.cpp,

1. Single Inheritance
In Single inheritance, class is derived from only one base class.
Syntax:
class base {
//…
};
class derived: [access_to_base] base {
//….
}

2. Multiple Inheritance
A class is derived from two or more base class.
Syntax:

class derived:[access_to_base1] base1, [access_to_base2] base2


{
//member of derived class
}

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Example:
class B1
{
//…
};
class B2
{
//…
};
class D: public B1, protected B2
{
//..
};

3. Multilevel inheritance

 The derivation of a class from another derived class is called multilevel inheritance.
 A new class that is derived from the base class serves as a base for further inheritance.
 In case of second derivation, the members inherited as protected or public form first
inheritance can be visible from the second derived class.

class A
{
//…
};
class B : public A
{
//…
};
class C: public B
{
//..
};

4. Hierarchical inheritance

 Classes are derived from single base class.


 Eg. Animal is the base class from which dog, cat, cow can be derived and the new
class can be base for other new classes.
 Syntax:

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
class derived: [access_to_base] base {
//…
};
class derived2:[access_to_base] base {
//…
};
.
class derivedn:[ access_to_base] base {
//…
}

Constructors and Destructors in Inheritance

Refer programs: coninherit.cpp and coninheritance.cpp

Invocation of constructors and destructors depends on the type of inheritance being


implemented. We have presented you the sequence in which constructors and
destructors get called in single and multiple inheritance.

1. Constructor and destructor in single inheritance

• Base class constructors are called first and the derived class constructors are called
next in single inheritance.

• Destructor is called in reverse sequence of constructor invocation i.e. The destructor


of the derived class is called first and the destructor of the base is called next.

Refer program coninherit.cpp

Here, Base is inherited first, so the constructor of class Base is called first and then
constructor of class Derived is called next.

However, the destructor of derived class is called first and then destructor of the base
class which is mentioned in the derived class declaration is called from last towards first
in sequentially.

2. Constructor and destructor in multiple inheritance

• Constructors from all base class are invoked first and the derived class constructor is
called.

• Order of constructor invocation depends on the order of how the base is inherited.

• For example:

class D:public B, public C {


//…
}

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Here, B is inherited first, so the constructor of class B is called first and then constructor
of class C is called next.

• However, the destructor of derived class is called first and then destructor of the base
class which is mentioned in the derived class declaration is called from last towards first
in sequentially.

To further understand the ambiguity that arise due to multiple instances / objects
(constructors and destructors) in inheritance. Refer the program and figure below:

Constraints of Multiple Inheritance (Ambiguity in Multiple / Hybrid inheritance)

Refer program: #Inheritancediamond.cpp (implementing diamond problem and


solution using virtual base class)
Implement the diamond problem and solution to diamond problem, with following
problem statement:

# The classes Cyber and Gaming derived from CSE. Class AIML derived from: Cyber,
Gaming, and CSE. Consider the inheritance access is public. Then instantiate the object of
AIML.

Concept of Virtual base class in C++

Virtual base classes are used in virtual inheritance in a way of preventing multiple
“instances” of a given class appearing in an inheritance hierarchy when using multiple
inheritances.

Need for Virtual Base Classes:

Consider the situation where we have one class A .This class is A is inherited by two
other classes B and C. Both these class are inherited into another in a new class D as
shown in figure below.

//Example of constructor and Output: Without virtual keyword


destructor operation in multiple
inheritance & virtual class A class constructor
#include<iostream> B class constructor
using namespace std; A class constructor
class A C class constructor
{ D class constructor
public: D class destructor
A() C class destructor
{ A class destructor
cout<<"A class constructor"<<endl; B class destructor
} A class destructor
~A()

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
{
cout<<"A class destructor"<<endl;
} Output: with virtual keyword
};
class B : virtual public A
{ A class constructor
public: B class constructor
B() C class constructor
{ D class constructor
cout<<"B class constructor"<<endl; D class destructor
} C class destructor
~B() B class destructor
{ A class destructor
cout<<"B class destructor"<<endl;
}
};
class C: virtual public A
{
public: Note: Using the keyword virtual
C() before derivation type enables virtual
{ inheritance for class D.
cout<<"C class constructor"<<endl;
}
~C()
{
cout<<"C class destructor"<<endl;
}
};
class D:public B, public C
{
public:
D()
{
cout<<"D class
constructor"<<endl;
}
~D()
{
cout<<"D class destructor"<<endl;
}
};
int main()
{
D d;
return 0;
}

Abstract Class (Interfaces) in C++

Refer programs: abstractclass.cpp and abstractclass1.cpp

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
In C++, we use terms abstract class and interface interchangeably. A class with pure
virtual function is known as abstract class. Or the class which has at least one pure
virtual function that is called an “abstract class”. We can never instantiate the abstract
class i.e. we cannot create an object of the abstract class.

For example the following function is a pure virtual function:

virtual void fun() = 0;

o A pure virtual function is marked with a virtual keyword and has = 0 after its
signature.
o You can call this function an abstract function as it has no body.
o The derived class must give the implementation to all the pure virtual functions
of parent class else it will become abstract class by default.

Why we need a abstract class?

Let’s understand this with the help of a real life example. Lets say we have a class
Animal, animal sleeps, animal make sound, etc. For now I am considering only these two
behaviours and creating a class Animal with two functions sound() and sleeping().

Now, we know that animal sounds are different cat says “meow”, dog says “woof”. So
what implementation do I give in Animal class for the function sound(), the only and
correct way of doing this would be making this function pure abstract so that I need not
give implementation in Animal class but all the classes that inherits Animal class must
give implementation to this function. This way I am ensuring that all the Animals have
sound but they have their unique sound.

Rules of Abstract Class

1) As we have seen that any class that has a pure virtual function is an abstract class.

2) We cannot create the instance of abstract class (Animal). For example: If I have
written this line: Animal obj; in the program, it would have caused compilation error.

3) We can create pointer and reference of base abstract class points to the instance of
child class. For example, this is valid: Animal *a;

Refer program: ambiguity.cpp

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Run time polymorphism and function (method) overriding

Runtime polymorphism is also known as dynamic polymorphism or late binding. In


runtime polymorphism, the function call is resolved at run time.

In contrast, to compile time or static polymorphism, the compiler deduces the object at
run time and then decides which function call to bind to the object. In C++, runtime
polymorphism is implemented using method or function overriding.

To understand the concept of Run time polymorphism - function overriding refer


program virtualfun.cpp and overriding.cpp

Function / Method Overriding

Function overriding is the mechanism using which a function defined in the base class is
once again defined in the derived class. In this case, we say the function is overridden in
the derived class.

 We should remember that function overriding cannot be done within a class.


 The function is overridden in the derived class only. Hence inheritance should be
present for function overriding.
 The second thing is that the function from a base class that we are overriding
should have the same signature or prototype i.e. it should have the same name,
same return type and same argument list.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Output:
print derived class
show base class

Virtual Functions

For the overridden function should be bound dynamically to the function body, we
make the base class function virtual using the “virtual” keyword. This virtual function is
a function that is overridden in the derived class and the compiler carries out late or
dynamic binding for this function.

So in the above class definition of Base, we made print () function as “virtual”. As the
base class function is made virtual, when we assign derived class object to base class
pointer and call print() function, the binding happens at runtime.

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University
Thus, as the base class pointer contains derived class object, the print () function body
in the derived class is bound to function print () and hence the output.

In C++, the overridden function in derived class can also be private. The compiler only
checks the type of the object at compile time and binds the function at run time, hence it
doesn’t make any difference even if the function is public or private.

Note that if a function is declared virtual in the base class, then it will be virtual in all of
the derived classes.

 Virtual functions ensure that the correct function is called for an object,
regardless of the type of reference (or pointer) used for function call.
 They are mainly used to achieve Runtime polymorphism
 Functions are declared with a virtual keyword in base class.
 The resolving of function call is done at Run-time.
 Virtual functions cannot be static and also cannot be a friend function of another
class.
 Virtual functions should be accessed using pointer or reference of base class type
to achieve run time polymorphism.
 The prototype of virtual functions should be same in base as well as derived
class.
 They are always defined in base class and overridden in derived class. It is not
mandatory for derived class to override (or re-define the virtual function), in
that case base class version of function is used.
 A class may have virtual destructor but it cannot have a virtual constructor.

How late binding actually happens. Refer note below:

Special note: The virtual function is bound to the function body accurately at runtime
by using the concept of the virtual table (VTABLE) and a hidden pointer called _vptr.
Both these concepts are internal implementation and cannot be used directly by the
program.

Experiments (programs) performed in Lab/Classroom are


already shared for reference.

Note: The document presents the notes on Module-III of ‘OOP with C++’. The students has
to use the creativity to answer the questions asked in examination. The answers should be
accompanied with suitable examples, syntax and diagrams (as applicable).

Prepared by: Prof. Anand Motwani, Faculty, SCSE, VIT Bhopal University

You might also like