304 OOPS Unit - 3
304 OOPS Unit - 3
Polymorphism
Polymorphism means many forms. It is an object-oriented programming concept that refers to the
ability of a variable, function, or object to take on multiple forms, meaning the behavior of the same
object or function can vary in different contexts.
Polymorphism can occur within a class and when multiple classes are related by inheritance.
Polymorphism is a word that combines "poly," meaning many, with "morphs," meaning forms,
which together means many forms. In C++, polymorphism refers to the concept where the behavior
of the same object or function is different in different contexts.
"I was right." In this sentence, the word "right" means "correct."
"Please take a right turn." In this sentence, the word "right" refers to the "right
direction."
1. CompileTimePolymorphism
2. RuntimePolymorphism
Compile-time polymorphism, also known as static polymorphism, occurs when the decision about which
function or method to call is made at compile time. This is possible because the C++ compiler has access to
information about function signatures and types before the program runs. The compiler uses this
information to determine which function to call based on the data types and number of parameters
provided. Since the choice is made during the compilation phase, it is known as compile-time
polymorphism.
Types of Compile-Time Polymorphism in C++
1. Function Overloading
Definition: Function overloading allows multiple functions with the same name but
different parameter lists (different number or types of parameters) to be defined. The
appropriate function is selected based on the arguments provided in the function call.
#include<conio.h>
#include<iostream.h>
//1.function with one argument
void area(int x)
{
float ar;
ar=3.14*x*x;
cout<<"\nArea of a circle is"<<ar;
}
//2.function with two argument
void area(int x,int y)
{
float ar;
ar=x*y;
cout<<"\nArea of a rectangle is"<<ar;
}
//3.function with two argument different datatype
void area(float x,int y)
{
int ar;
ar=x*y;
cout<<"\nArea of a rectangle is"<<ar;
}
void main()
{
int m;
clrscr();
Akansha Srivastav Page 2
Polymorphism
2. Operator Overloading
Definition: Operator overloading allows you to define custom behavior for operators (e.g., +, -, *, /)
when they are used with user-defined types (classes). The appropriate operator function is selected
based on the types of operands involved.
When an operator is updated to be used for user-defined data types(objects etc.), this is known as
operator overloading.To use operator overloading, at least one operand must be a user-defined
data type.
Note:
Bit Manipulation: &, |, ^, <<, >> and |=, &=, >>=, <<=, ^=
Note:
New and Delete operators can be overloaded globally, or they can be overloaded for specific
classes. If these operators are overloaded using the member function for a class, they are
overloaded only for that specific class.
Example: (Unary)
#include<iostream.h>
#include<conio.h>
class Simple
{
int x,y,z;
public:
void getdata()
{
x=5;
y=6;
z=12;
}
void dispdata();
void operator++()
{
x++;
y++;
z++;
}
};
void Simple::dispdata()
{
cout<<"\n Values of Simple";
cout<<"\nx="<<x;
cout<<"\ny="<<y;
cout<<"\nz="<<z;
}
void main()
{
Simple s1;
clrscr();
s1.getdata();
s1.dispdata();
++s1;
s1.dispdata();
getch();
}
Example : (Binary)
#include<iostream.h>
#include<conio.h>
Class test
{
int x;
Public:
test()
{}
test(int a)
Akansha Srivastav Page 4
Polymorphism
{
x=a;
}
test operator +(test t2)
{
test t3;
t3.x=x+t2.x;
return(t3);
}
void display()
{
cout<<x<<endl;
}
};
void main()
{
clrscr();
test t1,t2,t3;
t1=test(2);
t2=test(3);
t3=t1+t2;
t1.display();
t2.display(); Cout<<”sum:”<<endl;
t3.display();
getch();
}
Runtime Polymorphism
Runtime polymorphism occurs when functions are resolved at runtime rather than compile time
when a call to an overridden method is resolved dynamically at runtime rather than compile time.
It's also known as late binding or dynamic binding.
The following sections will show an example of overriding with and without the virtual keyword.
In this example, the function show in the base class is not marked as virtual. As a result,
the function call is determined at compile time, and runtime polymorphism does not occur.
#include <iostream.h>
class Base {
public:
void show() {
cout << "Base class show function" << endl;
}
};
void main()
{
Base* bptr;
Derived d;
bptr = &d;
bptr->show(); // Calls Base class show function due to non-virtual function
}
Output:
Base class show function
In this example, the function show in the base class is marked as virtual. This allows runtime
polymorphism, meaning the function call is determined at runtime based on the type of object that the
base class pointer actually points to.
#include <iostream.h>
class Base {
public:
virtual void show() {
cout << "Base class show function" << endl;
}
};
Explanation
Without virtual: The show function in the Base class is not marked as virtual. As a
result, the function call is bound at compile time. Even though bptr is pointing to a Derived
object, the Base class version of show is called.
With virtual: The show function in the Base class is marked as virtual. This enables
runtime polymorphism. When bptr->show() is called, the program determines at runtime
that bptr actually points to a Derived object, so the Derived class version of show is
executed.
This demonstrates how the use of the virtual keyword allows for dynamic method dispatch,
enabling more flexible and extensible code in C++.
A pure virtual function is a virtual function in C++ for which we need not to write any function
definition and only we have to declare it. It is declared by assigning 0 in the declaration.
An abstract class is a class in C++ which have at least one pure virtual function.
Abstract class can have normal functions and variables along with a pure virtual function.
Abstract class cannot be instantiated, but pointers and references of Abstract class type can be created.
Abstract classes are mainly used for Upcasting, so that its derived classes can use its interface.
If an Abstract Class has derived class, they must implement all pure virtual functions, or else they will become
Abstract too.
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.
#include<iostream.h>
class B
{
public:
virtual void s() = 0; // Pure Virtual Function
};
class D:public B
{
public:
void s() {
cout << "Virtual Function in Derived class\n";
}
};
void main()
{
B *b;
D dobj;
b = &dobj;
b->s();
}
Conclusion
Polymorphism in C++ is when the behavior of the same object or function is different in different
contexts. It has two types: Compile-time Polymorphism and Runtime Polymorphism.
In Compile-time Polymorphism, the function to be invoked is decided at compile time only. It is
achieved using function or operator overloading.
In Runtime Polymorphism, the function invoked is decided at run time. It is achieved using function
overriding and virtual functions.
The virtual function must be declared using the keyword virtual in the base class.
A Pure Virtual Function is a virtual function declared in the base class without a definition.
Friend Function:
Que: In which circumstances can a function be made a friend? Write the advantage of a friend function.
Demonstrate one example of a friend function.
A friend function is a special type of function that is declared inside the class. A friend function can
access the private, protected, and public data of the class.
The keyword friend is used before the return type of the function declaration/prototype.
If a function is defined as a friend function in C++, then the protected and private data of a class can
be accessed using the function.
By using the keyword friend, the compiler knows that the given function is a friend function.
For accessing the data, the declaration of a friend function should be done inside the body of a
class, starting with the keyword '
class class_name {
// Friend function declaration
friend data_type function_name(argument/s); // Syntax of friend function
};
In the above declaration, the friend function is preceded by the keyword friend. The
function can be defined anywhere in the program, just like a normal C++ function.
The function definition does not use either the keyword friend or the scope resolution
operator (::).
The function is not in the scope of the class to which it has been declared as a friend.
It cannot be called using the object, as it is not in the scope of that class.
It can be invoked like a normal function without using the object.
It cannot access the member names directly and has to use an object name and dot membership
operator with the member name.
It can be declared either in the private or the public part of the class.
#include <iostream.h>
#include <conio.h>
class Sample {
private:
int a, b;
public:
void getData() {
a = 25;
b = 40;
}
int main() {
Sample x;
x.getData();
cout << "Mean value = " << mean(x) << endl;
getch();
return 0;
}
public:
B()
{
y=20;
}
friend void min(A,B);
};
void min(A a,B b)
{
if(a.x<b.y)
cout<<"\n\n\n"<<a.x<<"is smaller";
else
cout<<"\n\n\n"<<b.y<<"is smaller";
}
void main()
{
clrscr();
A a;
B b;
min(a,b);
getch();
#include<iostream.h>
#include<conio.h>
class B;
class A
{
int x;
public:
A()
{
x=20;
}
void putA()
{
cout<<"\n Value of A x:"<<x;
}
friend void swap(A &,B &);
};
class B
{
int y;
public:
B()
{
y=30;
}
void putB()
{
cout<<"\n Value of B y:"<<y;
}
friend void swap(A &,B &);
};
void swap(A &a,B &b)
{
int temp;
cout<<"Before swaping";
cout<<"\n Value of A x:"<<a.x;
cout<<"\n Value of B y:"<<b.y;
temp=a.x;
a.x=b.y;
b.y=temp;
cout<<"\n After After swaping";
cout<<"\n Value of A x:"<<a.x;
cout<<"\n Value of B y:"<<b.y;
}
void main()
{
A a;
B b;
clrscr();
swap(a,b);
a.putA();
b.putB();
getch();
}
Such a base class is known as a virtual base class. This can be achieved by preceding the base
class’ name with the word virtual.
The duplication of inherited members due to these multiple paths can be avoided by making the
common base class (ancestor class) as virtual base class.
Example:
#include <iostream.h>
class Student {
protected:
int roll_number;
public:
void get_number(int a) {
roll_number = a;
}
void put_number() const {
cout << "Roll no: " << roll_number << "\n";
}
};
float total;
void display();
};
void Result::display() {
total = part1 + part2 + score;
put_number();
put_marks();
put_score();
cout << "Total Score = " << total << "\n";
}
int main() {
Result stu;
stu.get_number(123);
stu.get_marks(27.5, 33.0);
stu.get_score(6.0);
stu.display();
return 0;
}
this is a pointer that points to the object for which this function was called.
This unique pointer is automatically passed to a member function when it is called. The pointer this acts
as an implicit argument to all the member functions.
class abc
{
int a;
public:
void display()
{
this->a=123;
cout<<a;
}
};
void main()
{
clrscr();
abc a;
a.display();
getch();
}
// Abstract class
#include <iostream.h>
class Shape {
public:
// Pure virtual function
virtual void draw() const = 0;
// Derived class
class Circle : public Shape {
public:
void draw() const override {
cout << "Drawing a circle." << endl;
}
};
int main() {
// Shape shape; // This line would cause a compilation error because Shape is abstract
Circle circle;
circle.draw(); // Calls the overridden draw function in Circle
circle.describe(); // Calls the non-pure virtual function from Shape
return 0;
}