Oop Notes Unit 3
Oop Notes Unit 3
Function overloading, Run Time Polymorphism- Pointers to Base class, virtual function and its
significance in C++, pure virtual function and virtual table, virtual destructor, abstract base class.
Page 1 of 20
3. 1 Introduction to Polymorphism
The term "Polymorphism" is the combination of "poly" + "morphs" which means many forms. It is a greek
word. In object-oriented programming, we use 3 main concepts: inheritance, encapsulation, and
polymorphism.
Let's consider a real-life example of polymorphism. A lady behaves like a teacher in a classroom, mother
or daughter in a home and customer in a market. Here, a single person is behaving differently according
to the situations.
The overloaded functions are invoked by matching the type and number of arguments. This information
is available at the compile time and, therefore, compiler selects the appropriate function at the compile
Page 2 of 20
time. It is achieved by function overloading and operator overloading which is also known as static binding
or early binding.
Run time polymorphism is achieved when the object's method is invoked at the run time instead of
compile time. It is achieved by method overriding which is also known as dynamic binding or late binding.
1. methods,
2. constructors, and
3. indexed properties
Page 3 of 20
Operator overloading
Operator overloading is an important concept in C++. It is polymorphism in which an operator is
overloaded to give user defined meaning to it. Overloaded operator is used to perform operation on user-
defined data type.
The unary operators operate on the object for which they were called and normally, this operator appears
on the left side of the object, as in !obj, -obj, and ++obj but sometime they can be used as postfix as well
like obj++ or obj--.
Example
#include <iostream>
using namespace std;
class Distance {
private:
int feet; // 0 to infinite
int inches; // 0 to 12
public:
// required constructors
Distance() {
feet = 0;
inches = 0;
}
Distance(int f, int i) {
feet = f;
inches = i;
}
Page 4 of 20
}
int main() {
Distance D1(11, 10), D2(-5, 11);
return 0;
}
When the above code is compiled and executed, it produces the following result −
F: -11 I:-10
F: 5 I:-11
Example
#include <iostream>
using namespace std;
class Box {
public:
double getVolume(void) {
return length * breadth * height;
}
void setLength( double len ) {
length = len;
}
Page 5 of 20
void setBreadth( double bre ) {
breadth = bre;
}
void setHeight( double hei ) {
height = hei;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// volume of box 1
volume = Box1.getVolume();
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
Page 6 of 20
Box3 = Box1 + Box2;
// volume of box 3
volume = Box3.getVolume();
cout << "Volume of Box3 : " << volume <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Overloadable/Non-overloadable Operators
+ - * / % ^
& | ~ ! , =
< > <= >= ++ --
<< >> == != && ||
+= -= /= %= ^= &=
|= *= <<= >>= [] ()
-> ->* new new [] delete delete []
:: .* . ?:
Example
#include <bits/stdc++.h>
using namespace std;
class Time {
int hour;
int mins;
Page 7 of 20
public:
// Default Constructor
Time()
{
hour = 0;
mins = 0;
}
// Parameterized Constructor
Time(int t)
{
hour = t / 60;
mins = t % 60;
}
int main()
{
// Object of Time class
Time T1;
int dur = 95;
return 0;
}
Output
Page 8 of 20
1. Implicit Type Conversion Also known as ‘automatic type conversion’.
Example
#include <iostream>
using namespace std;
int main()
{
int x = 10; // integer x
char y = 'a'; // character c
Output
x = 107
y = a
z = 108
2. Explicit Type Conversion: This process is also called type casting and it is user-defined.
Example
#include <iostream>
using namespace std;
int main()
{
double x = 1.2;
Page 9 of 20
// Explicit conversion from double to int
int sum = (int)x + 1;
return 0;
}
Output
Sum = 2
In operator overloading, any C++ existing operations can be overloaded, but some exceptions.
1. Conditional [?:], size of, scope(::), Member selector(.), member pointer selector(.*) and the
casting operators.
2. We can only overload the operators that exist and cannot create new operators or rename
existing operators.
3. At least one of the operands in overloaded operators must be user-defined, which means we
cannot overload the minus operator to work with one integer and one double. However, you could
overload the minus operator to work with an integer and a mystring.
5. All operators keep their default precedence and associations (what they use for), which cannot
be changed.
Page 10 of 20
3. When a double is cast to an int, the fractional part of a double is discarded which causes the loss
of fractional part of data.
Sometimes logic required to use only one or two data members as a variable and another one as a
constant to handle the data. In that situation, mutability is very helpful concept to manage classes.
Example
#include <iostream>
using namespace std;
code
class Test {
public:
int a;
mutable int b;
Test(int x=0, int y=0) {
a=x;
b=y;
}
void seta(int x=0) {
a = x;
}
void setb(int y=0) {
b = y;
}
void disp() {
cout<<endl<<"a: "<<a<<" b: "<<b<<endl;
}
};
int main() {
const Test t(10,20);
cout<<t.a<<" "<<t.b<<"\n";
// t.a=30; //Error occurs because a can not be changed, because object is
constant.
t.b=100; //b still can be changed, because b is mutable.
cout<<t.a<<" "<<t.b<<"\n";
return 0;
}
Page 11 of 20
Explicit Keyword in C++ is used to mark constructors to not implicitly convert types in C++. It is optional
for constructors that take exactly one argument and work on constructors (with a single argument) since
those are the only constructors that can be used in typecasting.
Example
class Complex {
private:
double real;
double imag;
public:
// Default constructor
Complex(double r = 0.0,
double i = 0.0) : real(r),
imag(i)
{
}
// Driver Code
int main()
{
// a Complex object
Complex com1(3.0, 0.0);
if (com1 == 3.0)
cout << "Same";
else
cout << "Not Same";
return 0;
}
Page 12 of 20
Output
Same
Example
#include <iostream>
using namespace std;
class printData {
public:
void print(int i) {
cout << "Printing int: " << i << endl;
}
void print(double f) {
cout << "Printing float: " << f << endl;
}
void print(char* c) {
cout << "Printing character: " << c << endl;
}
};
int main(void) {
printData pd;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Page 13 of 20
Printing int: 5
Printing float: 500.263
Printing character: Hello C++
Example
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
};
int main () {
Rectangle rect;
Triangle trgl;
Polygon * ppoly1 = ▭
Polygon * ppoly2 = &trgl;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << rect.area() << '\n';
cout << trgl.area() << '\n';
Page 14 of 20
return 0;
}
Output
20
10
It is used to tell the compiler to perform dynamic linkage or late binding on the function.
There is a necessity to use the single pointer to refer to all the objects of the different classes.
So, we create the pointer to the base class that refers to all the derived objects. But, when base
class pointer contains the address of the derived class object, always executes the base class
function. This issue can only be resolved by using the 'virtual' function.
When the function is made virtual, C++ determines which function is to be invoked at the runtime
based on the type of the object pointed by the base class pointer.
5. A virtual function must be defined in the base class, even though it is not used.
6. The prototypes of a virtual function of the base class and all the derived classes must be identical.
If the two functions with the same name but different prototypes, C++ will consider them as the
overloaded functions.
Page 15 of 20
8. Consider the situation when we don't use the virtual keyword.
Example
#include <iostream>
using namespace std;
class A
{
int x=5;
public:
void display()
{
std::cout << "Value of x is : " << x<<std::endl;
}
};
class B: public A
{
int y = 10;
public:
void display()
{
std::cout << "Value of y is : " <<y<< std::endl;
}
};
int main()
{
A *a;
B b;
a = &b;
a->display();
return 0;
}
Output
Value of x is : 5
An abstract class is a class in C++ which have at least one pure virtual function.
1. Abstract class can have normal functions and variables along with a pure virtual function.
Page 16 of 20
2. Abstract class cannot be instantiated, but pointers and references of Abstract class type can be
created.
3. Abstract classes are mainly used for Upcasting, so that its derived classes can use its interface.
4. If an Abstract Class has derived class, they must implement all pure virtual functions, or else
they will become Abstract too.
5. We can’t create object of abstract class as we reserve a slot for a pure virtual function in Vtable,
but we don’t put any address, so Vtable will remain incomplete.
Example
#include<iostream>
using namespace std;
class B {
public:
virtual void s() = 0; // Pure Virtual Function
};
class D:public B {
public:
void s() {
cout << "Virtual Function in Derived class\n";
}
};
int main() {
B *b;
D dobj;
b = &dobj;
b->s();
}
Output
Virtual Function in Derived class
Example
Page 17 of 20
#include<iostream>
using namespace std;
class b {
public:
b() {
cout<<"Constructing base \n";
}
virtual ~b() {
cout<<"Destructing base \n";
}
};
class d: public b {
public:
d() {
cout<<"Constructing derived \n";
}
~d() {
cout<<"Destructing derived \n";
}
};
int main(void) {
d *derived = new d();
b *bptr = derived;
delete bptr;
return 0;
}
Output
Constructing base
Constructing derived
Destructing derived
Destructing base
Example
#include <iostream>
using namespace std;
// Base class
Page 18 of 20
class Shape {
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Derived classes
class Rectangle: public Shape {
public:
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
return 0;
}
Page 19 of 20
Output
Page 20 of 20