0% found this document useful (0 votes)
17 views21 pages

Module 4

Module IV of the ES203 course on Object Oriented Programming Using C++ focuses on the concept of polymorphism, explaining its types such as compile-time and run-time polymorphism, along with function and operator overloading. It covers practical examples of function overloading, operator overloading, and the use of virtual functions to achieve dynamic behavior in classes. The module also discusses the significance of the 'this' pointer and how base class pointers can point to derived class objects, emphasizing the importance of virtual functions for runtime polymorphism.

Uploaded by

pbcg.common
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)
17 views21 pages

Module 4

Module IV of the ES203 course on Object Oriented Programming Using C++ focuses on the concept of polymorphism, explaining its types such as compile-time and run-time polymorphism, along with function and operator overloading. It covers practical examples of function overloading, operator overloading, and the use of virtual functions to achieve dynamic behavior in classes. The module also discusses the significance of the 'this' pointer and how base class pointers can point to derived class objects, emphasizing the importance of virtual functions for runtime polymorphism.

Uploaded by

pbcg.common
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

Module IV: Polymorphism

ES203 – Object Oriented Programming Using C++

Dr. Sreemana Datta


Asst. Professor
Department of Computer Science & Engineering
Amity School of Engineering & Technology
Amity University, Jharkhand

February 19, 2026

ES203 – OOP Using C++ Module IV: Polymorphism 1 / 21


Module IV — Roadmap

1 Polymorphism & Function Overloading

2 Operator Overloading

3 Pointers, this Pointer & Polymorphism by Parameter

4 Virtual Functions & Pure Virtual Functions

ES203 – OOP Using C++ Module IV: Polymorphism 2 / 21


What is Polymorphism?
Polymorphism (Greek: poly = many, morph = form)
Polymorphism
The ability of a single interface to represent different underlying forms
(implementations).
Compile-Time Run-Time
Real-Life Polymorphism
A person can play multiple roles:
At home → parent Function Overloading
Operator Overloading Virtual Functions
At office → manager
At shop → customer
At school → guardian
Same person, different behavior depending on context!

ES203 – OOP Using C++ Module IV: Polymorphism 3 / 21


Compile-Time vs Run-Time Polymorphism
Compile-Time (Static) Run-Time (Dynamic)
Resolved during compilation Resolved during execution
Faster (no runtime overhead) Slight overhead (vtable lookup)
Function Overloading Virtual Functions
Operator Overloading Function Overriding
Also called early binding Also called late binding
Compiler decides which function Runtime decides which function

Analogy
Compile-time: A restaurant menu with pictures — you know exactly what you’ll get before ordering. The decision is made at the menu (compile time).

Run-time: A “Chef’s Special” — you only find out what dish it is when it arrives (runtime). The chef decides based on what’s fresh today!

ES203 – OOP Using C++ Module IV: Polymorphism 4 / 21


Function Overloading — Same Name, Different Signatures
Function Overloading: Multiple functions with the same name but different parameter lists.
# include < iostream >
using namespace std ;

// Overloaded " area " function for different shapes


double area ( double radius ) { // Circle
return 3.14159 * radius * radius ;
}

double area ( double length , double width ) { // Rectangle


return length * width ;
}

double area ( double base , double height , bool isTriangle ) { // Triangle


return 0.5 * base * height ;
}

int main () {
cout « " Circle area : " « area (5.0) « endl ; // 78.54
cout « " Rectangle area : " « area (4.0 , 6.0) « endl ; // 24.0
cout « " Triangle area : " « area (3.0 , 8.0 , true ) « endl ; // 12.0
return 0;
}

The compiler picks the right function based on the number and types of arguments. This is resolved at compile time.

ES203 – OOP Using C++ Module IV: Polymorphism 5 / 21


Function Overloading — Rules & Pitfalls
Functions can be overloaded by:
1 Number of parameters: f(int) vs f(int, int)
2 Type of parameters: f(int) vs f(double)
3 Order of parameters: f(int, double) vs f(double, int)

Functions CANNOT be overloaded by:


Return type alone!

int f(int x); and double f(int x); — ERROR!

Why? Because the compiler sees f(5) and can’t decide which one you meant — you might ignore the return value!

Pro Tip
Also be careful with default arguments and overloading — they can create ambiguity!
void f(int a, int b = 0); and void f(int a); — calling f(5) is ambiguous!

ES203 – OOP Using C++ Module IV: Polymorphism 6 / 21


Operator Overloading — Making Operators Work for Your Classes

The Motivation
You can write 5 + 3 and the + operator knows how to add integers.

But what about c1 + c2 where c1 and c2 are Complex objects?

By default, the compiler doesn’t know how to add two Complex numbers. Operator overloading teaches it!

Syntax: return_type operatorsymbol (parameters) { ... }

Operators that CAN be overloaded:


+ - * / % ˆ & | ~! = < > += -= *= /= ++ – « » == != && || [] () -> new delete
Operators that CANNOT be overloaded:
:: (scope resolution), . (member access), .* (member pointer), ?: (ternary), sizeof

ES203 – OOP Using C++ Module IV: Polymorphism 7 / 21


Unary Operator Overloading
Unary operators work on a single operand: ++, –, -, !, ~
# include < iostream >
using namespace std ;

class Counter {
int count ;
public :
Counter ( int c = 0) : count ( c ) {}

// Overload PREFIX ++ (++ obj )


Counter operator ++() {
count ++;
return * this ; // Return the modified object
}

// Overload POSTFIX ++ ( obj ++)


// The ’ int ’ parameter is a DUMMY to distinguish from prefix
Counter operator ++( int ) {
Counter temp = * this ; // Save current state
count ++;
return temp ; // Return OLD value
}

// Overload unary minus ( - obj )


Counter operator -() {
return Counter ( - count ) ;
}

void display () { cout « " Count : " « count « endl ; }


};

int main () {
Counter c (5) ;
(++ c ) . display () ; // Count : 6 ( prefix : increment then return )
( c ++) . display () ; // Count : 6 ( postfix : return then increment )
c . display () ; // Count : 7 ( now shows the postfix effect )
( - c ) . display () ; // Count : -7 ( unary minus )
return 0;
}

ES203 – OOP Using C++ Module IV: Polymorphism 8 / 21


Binary Operator Overloading
Binary operators work on two operands: +, -, *, /, ==, <, >, etc.
# include < iostream >
using namespace std ;

class Complex {
double real , imag ;
public :
Complex ( double r = 0 , double i = 0) : real ( r ) , imag ( i ) {}

// Overload + operator ( Binary : takes one param = right operand )


Complex operator +( const Complex & other ) const {
return Complex ( real + other . real , imag + other . imag ) ;
}

// Overload - operator
Complex operator -( const Complex & other ) const {
return Complex ( real - other . real , imag - other . imag ) ;
}

// Overload == operator
bool operator ==( const Complex & other ) const {
return ( real == other . real ) && ( imag == other . imag ) ;
}

void display () const {


cout « real « ( imag >= 0 ? " + " : " - " )
« ( imag >= 0 ? imag : - imag ) « " i " « endl ;
}
};

int main () {
Complex c1 (3.0 , 4.0) , c2 (1.5 , 2.5) ;
Complex c3 = c1 + c2 ; // Calls c1 . operator +( c2 )
Complex c4 = c1 - c2 ;
c3 . display () ; // 4.5 + 6.5 i
c4 . display () ; // 1.5 + 1.5 i
cout « ( c1 == c2 ? " Equal " : " Not Equal " ) « endl ;
return 0;
}

ES203 – OOP Using C++ Module IV: Polymorphism 9 / 21


Overloading « and » (Stream Operators)
# include < iostream >
using namespace std ;

class Point {
int x , y ;
public :
Point ( int x = 0 , int y = 0) : x ( x ) , y ( y ) {}

// Overload « ( must be FRIEND - left operand is ostream , not Point )


friend ostream & operator « ( ostream & out , const Point & p ) {
out « " ( " « p . x « " , " « p . y « " ) " ;
return out ; // Return stream for chaining : cout « p1 « p2 ;
}

// Overload »
friend istream & operator » ( istream & in , Point & p ) {
cout « " Enter x and y : " ;
in » p . x » p . y ;
return in ;
}
};

int main () {
Point p1 (3 , 7) ;
cout « " Point is : " « p1 « endl ; // Point is : (3 , 7)
// Reads just like a built - in type !

Point p2 ;
cin » p2 ; // Enter x and y : 5 10
cout « p2 ; // (5 , 10)
return 0;
}

Stream operators « and » must be friend functions because the left operand is ostream/istream, not your class.

ES203 – OOP Using C++ Module IV: Polymorphism 10 / 21


Operator Overloading — Rules Summary
Rules to Remember: Member vs Friend:
1 Cannot create new operators (no operator$$) Member function: left operand is this
2 Cannot change precedence or associativity c1 + c2 → [Link]+(c2)
3 Cannot change number of operands (+ stays binary) Friend function: both operands as params
4 At least one operand must be a user-defined type cout « c1 → operator«(cout, c1)
5 Some operators must be members: =, [], (), ->

Common Mistake
Don’t overload operators in ways that are counter-intuitive! If + is
overloaded for a Matrix class, it should add matrices, not subtract them!

ES203 – OOP Using C++ Module IV: Polymorphism 11 / 21


Polymorphism by Parameter
Polymorphism by parameter = function behavior changes based on the type or number of arguments passed. This is essentially
function overloading viewed from a polymorphic lens.
# include < iostream >
using namespace std ;

class Printer {
public :
// Same function name , different parameter TYPES
void print ( int i ) { cout « " Integer : " « i « endl ; }
void print ( double d ) { cout « " Double : " « d « endl ; }
void print ( string s ) { cout « " String : " « s « endl ; }

// Same function name , different NUMBER of parameters


void print ( int a , int b ) {
cout « " Two integers : " « a « " and " « b « endl ;
}
};

int main () {
Printer p ;
p . print (42) ; // Integer : 42
p . print (3.14) ; // Double : 3.14
p . print ( " Hello " ) ; // String : Hello
p . print (10 , 20) ; // Two integers : 10 and 20
return 0;
}

The parameter signature determines which version of print() is invoked — that’s polymorphism by parameter!

ES203 – OOP Using C++ Module IV: Polymorphism 12 / 21


Pointer to Objects
Just like pointers to basic types, you can have pointers to objects.
# include < iostream >
using namespace std ;

class Student {
public :
string name ;
int roll ;
Student ( string n , int r ) : name ( n ) , roll ( r ) {}
void display () { cout « name « " ( Roll : " « roll « ")" « endl ; }
};

int main () {
Student s1 ( " Amit " , 101) ;

// Pointer to object ( on stack )


Student * ptr = & s1 ;
ptr - > display () ; // Use -> with pointers !
cout « ptr - > name « endl ; // Amit
cout « (* ptr ) . roll « endl ; // 101 ( dereference then dot )

// Pointer to dynamically allocated object


Student * s2 = new Student ( " Priya " , 102) ;
s2 - > display () ; // Priya ( Roll : 102)
delete s2 ; // Don ’t forget !

return 0;
}

Use -> (arrow operator) with pointers to objects. Use . (dot operator) with objects directly.

ES203 – OOP Using C++ Module IV: Polymorphism 13 / 21


Base Class Pointer to Derived Object — The Key to Runtime Polymorphism
# include < iostream >
using namespace std ;

class Animal {
public :
void speak () { cout « " Animal speaks ... " « endl ; }
};

class Dog : public Animal {


public :
void speak () { cout « " Woof ! Woof ! " « endl ; }
};

int main () {
Animal * ptr ; // Base class pointer

Dog d ;
ptr = & d ; // Base pointer pointing to Derived object - OK !

ptr - > speak () ; // Prints : " Animal speaks ..." ( NOT " Woof !")
// WHY ? Because without ’ virtual ’, the compiler uses the
// POINTER TYPE ( Animal *) , not the ACTUAL OBJECT TYPE ( Dog )
// This is STATIC BINDING !
return 0;
}

Surprise!
Even though ptr points to a Dog, it calls Animal::speak()!
To fix this and get runtime polymorphism, we need virtual functions (next lecture!).

ES203 – OOP Using C++ Module IV: Polymorphism 14 / 21


this Pointer — The Hidden Self-Reference
Every non-static member function has a hidden parameter: this class Employee {
— a pointer to the calling object. string name ;
double salary ;
public :
// Use 1: Resolve ambiguity
Employee ( string name , double salary ) {
Analogy this - > name = name ;
this - > salary = salary ;
When you say “I want food”, the word “I” refers to yourself. You don’t }
need to say your name — “I” is implicit.
// Use 2: Method chaining
Similarly, this is the object’s way of saying “myself”. Employee & setName ( string name ) {
this - > name = name ;
return * this ; // Return self !
Uses of this: }

Employee & setSalary ( double s ) {


1 Resolve name conflicts this - > salary = s ;
return * this ;
2 Return current object }
3 Pass object to other functions
void display () {
cout « name « " : Rs . "
« salary « endl ;
}
};

int main () {
Employee e ( " ? " , 0) ;

// Method chaining ! ( like jQuery )


e . setName ( " Amit " )
. setSalary (50000) ;

e . display () ; // Amit : Rs .50000


return 0;
}

ES203 – OOP Using C++ Module IV: Polymorphism 15 / 21


Virtual Functions — The Magic of Runtime Polymorphism
Adding the virtual keyword tells the compiler: “Don’t decide at compile time — check the actual object type at runtime!”
# include < iostream >
using namespace std ;

class Animal {
public :
virtual void speak () { // VIRTUAL function !
cout « " Animal speaks ... " « endl ;
}
};

class Dog : public Animal {


public :
void speak () override { // Override base version
cout « " Woof ! Woof ! " « endl ;
}
};

class Cat : public Animal {


public :
void speak () override {
cout « " Meow ! Meow ! " « endl ;
}
};

int main () {
Animal * ptr ; // Base class pointer

Dog d ; Cat c ;
ptr = & d ;
ptr - > speak () ; // Woof ! Woof ! ( Dog ’s version --- RUNTIME decision !)

ptr = & c ;
ptr - > speak () ; // Meow ! Meow ! ( Cat ’s version --- RUNTIME decision !)
return 0;
}

ES203 – OOP Using C++ Module IV: Polymorphism 16 / 21


How Virtual Functions Work — The vtable
When a class has virtual functions, the compiler creates a hidden vtable Dog object
(virtual table) for the class:
vptr Dog’s vtable
1 Each class with virtual functions gets a vtable — an array of function pointers
2 Each object gets a hidden pointer (vptr) to its class’s vtable
Dog::speak()
3 At runtime, the vptr is followed to find the correct function

Small Overhead Cat object

Virtual functions have a slight performance cost: vptr Cat’s vtable


Extra memory for vptr (one pointer per object)
Extra memory for vtable (one per class) Cat::speak()
Indirect function call (pointer lookup)

ES203 – OOP Using C++ Module IV: Polymorphism 17 / 21


Virtual Functions: Practical Example — Shape Calculator
# include < iostream >
using namespace std ;

class Shape {
public :
virtual double area () = 0; // Pure virtual ( abstract )
virtual void display () {
cout « " Area = " « area () « endl ;
}
virtual ~ Shape () {} // Virtual destructor ( important !)
};

class Circle : public Shape {


double radius ;
public :
Circle ( double r ) : radius ( r ) {}
double area () override { return 3.14159 * radius * radius ; }
};

class Rectangle : public Shape {


double l , w ;
public :
Rectangle ( double l , double w ) : l ( l ) , w ( w ) {}
double area () override { return l * w ; }
};

int main () {
Shape * shapes [3]; // Array of base class pointers
shapes [0] = new Circle (5) ;
shapes [1] = new Rectangle (4 , 6) ;
shapes [2] = new Circle (3) ;

for ( int i = 0; i < 3; i ++) {


shapes [ i ] - > display () ; // Correct area () called for each !
delete shapes [ i ];
}
return 0;
}

ES203 – OOP Using C++ Module IV: Polymorphism 18 / 21


Pure Virtual Functions & Abstract Classes
A pure virtual function has no implementation in the base // ABSTRACT : Cannot instantiate
class: virtual void func() = 0; class Database {
public :
// Pure virtual functions
A class with one or more pure virtual functions is abstract — it virtual void connect () = 0;
virtual void query (
cannot be instantiated. string sql ) = 0;
virtual void disconnect () = 0;
Why use them? };

class MySQL : public Database {


Define a contract — “all derived classes MUST implement this” public :
void connect () override {
Create a common interface cout « " MySQL connected "
Prevent creation of incomplete objects « endl ;
}
void query ( string sql ) override {
cout « " MySQL : " « sql
« endl ;
Rule }
void disconnect () override {
If a derived class does NOT override ALL pure virtual functions, it also cout « " MySQL disconnected "
« endl ;
becomes abstract! }
};

class PostgreSQL : public Database {


public :
void connect () override {
cout « " PG connected "
« endl ;
}
void query ( string sql ) override {
cout « " PG : " « sql
« endl ;
}
void disconnect () override {
cout « " PG disconnected "
« endl ;
}
};

ES203 – OOP Using C++ Module IV: Polymorphism 19 / 21


Virtual vs Pure Virtual — Comparison
Virtual Function Pure Virtual Function
Has a default implementation No implementation (= 0)
Derived class may override Derived class must override
Class can be instantiated Class becomes abstract
Provides default behavior Defines a contract/interface
virtual void f() {...} virtual void f() = 0;

Virtual Destructor — Always Use It!


If a class has virtual functions, its destructor should also be virtual:

virtual ~Shape() {}

Without this, deleting a derived object through a base pointer may not call the derived destructor — causing resource leaks!

ES203 – OOP Using C++ Module IV: Polymorphism 20 / 21


Module IV — Recap ✓
Compile-Time Polymorphism: Runtime Polymorphism:
1 Function Overloading (different params) 1 Virtual Functions (virtual keyword)
2 Operator Overloading 2 vtable and vptr mechanism
Unary: ++, –, - 3 Pure Virtual Functions (= 0)
Binary: +, -, == 4 Abstract Classes
Stream: «, » (friend) 5 Virtual Destructors
3 Polymorphism by Parameter

Important Concepts: Next: Module V


Pointer to Objects (->) Strings, File Handling, Exception Handling, Templates, and the Standard
Template Library (STL)!
this pointer (self-reference)
Method chaining

ES203 – OOP Using C++ Module IV: Polymorphism 21 / 21

You might also like