Introduction to Object Oriented Programming Module-3
Module 3
Operator Overloading and Inheritance
Operator Overloading
Operator overloading in C++ is a feature that allows programmers to redefine the way
operators work for user-defined data types (such as classes and structures). By overloading an
operator, you can provide a custom implementation so that it can perform operations on objects in a
way that is meaningful to your program. For example, you can overload the + operator to add two
complex numbers or concatenate two strings.
Syntax:
return_type ClassName::operator<symbol>(parameter_list) {
// body of operator function
}
Operator overloading is done by defining a special function, called an operator function,
whose name is formed by the keyword operator followed by the symbol of the operator being
overloaded (e.g., operator+). This function can be defined either as a member function of a class or as
a friend function, depending on whether the left-hand operand needs to be an object of that class.
While operator overloading improves code readability and allows objects to behave like basic data
types, it must be used carefully to maintain clarity and avoid confusing the meaning of operators.
Important Points about Operator Overloading
1) For operator overloading to work, at least one of the operands must be a user-defined class object.
2) Assignment Operator: Compiler automatically creates a default assignment operator with every
class. The default assignment operator does assign all members of the right side to the left side and
works fine in most cases (this behaviour is the same as the copy constructor).
3) Conversion Operator: We can also write conversion operators that can be used to convert one type
to another type.
4) Not all operators can be overloaded: Some of the operators cannot be overloaded. They are
sizeof
typeid
Scope resolution (::)
Class member access operators (.(dot), .* (pointer to member operator))
Ternary or conditional (?:)
Overloading Unary Operator
The unary operators operate on a single operand and following are the examples of Unary operators −
The increment (++) and decrement (--) operators.
The unary minus (-) operator.
The logical not (!) operator.
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--.
1 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
Eg: Overloading using class member function
#include <iostream>
using namespace std;
class Number {
int a,b;
public:
Number(int x,int y) {
a = x;
b=y;
}
// Overloading unary - operator
Number operator-() {
Number temp(-a,-b); // Negate the value
return temp;
}
void display() {
cout << "a: " << a << endl;
cout << "b: " << b << endl;
}
};
int main() {
Number n1(10,2);
Number n2 = -n1; // Calls operator-()
cout << "Original object: ";
[Link]();
cout << "After applying unary - operator: ";
[Link]();
return 0;
}
The function operator-() is defined inside the class without parameters because unary operators
work on a single operand (the calling object). It creates a temporary Number object with the negated
value and returns it. When -n1 is written, it automatically calls [Link]-().
Eg: Overloaded using friend function
#include <iostream>
using namespace std;
class Number {
int a, b;
public:
Number(int x, int y) {
a = x;
b = y;
}
2 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
// Friend function declaration
friend Number operator-(Number obj);
void display() {
cout << "a: " << a << endl;
cout << "b: " << b << endl;
}
};
// Friend function definition
Number operator-(Number obj) {
// Can access private members directly because it's a friend
Number temp(-obj.a, -obj.b);
return temp;
}
int main() {
Number n1(10, 2);
Number n2 = -n1; // Calls friend operator-()
cout << "Original object: " << endl;
[Link]();
cout << "After applying unary - operator: " << endl;
[Link]();
return 0;
}
Feature Member Function Friend Function
Definition Defined inside the class using the scope Declared in the class with the
resolution operator (ClassName::). keyword friend and defined outside
the class.
Access to Has direct access to all members of the class. Also has direct access because it is
Private declared as a friend.
Members
Number of Takes no parameters because the calling Takes one parameter (the calling
Parameters object is implied (this pointer). object is passed explicitly).
(Unary
Operator)
Number of Takes one parameter (the left-hand operand Takes two parameters (both
Parameters is the calling object). operands passed explicitly).
(Binary
Operator)
Function Called like [Link]+(otherObj) Called like a normal function
Call internally when you write obj + otherObj. internally when you write obj +
otherObj.
When Useful When the left-hand operand must be an When the left-hand operand is not
object of the class. necessarily an object of the class, or
when symmetrical access is needed
for both operands.
Example return_type friend return_type
Syntax ClassName::operator<symbol>(param_list) operator<symbol>(ClassName
obj1, ClassName obj2)
Overloading Binary Operator
3 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
The binary operators take two arguments and following are the examples of Binary operators.
You use binary operators very frequently like addition (+) operator, subtraction (-) operator and
division (/) operator.
Eg: Overloading + operator to add two complex numbers using member function
#include <iostream>
using namespace std;
class Complex {
float real;
float imag;
public:
// Constructor
Complex(float r = 0, float i = 0) {
real = r;
imag = i;
}
// Overloading binary + operator
Complex operator+(Complex obj) {
Complex temp;
[Link] = real + [Link]; // Add real parts
[Link] = imag + [Link]; // Add imaginary parts
return temp;
}
// Display function
void display() {
cout << real << " + " << imag << "i" << endl;
}
};
int main() {
Complex c1(3.5, 2.5);
Complex c2(1.6, 4.2);
Complex c3;
c3 = c1 + c2; // Calls operator+()
cout << "First Complex Number: ";
[Link]();
cout << "Second Complex Number: ";
[Link]();
cout << "Sum of Complex Numbers: ";
[Link]();
return 0;
}
The + operator is overloaded so it can add two Complex objects just like normal numbers. The
function operator+ takes one parameter (obj) for the right-hand operand. The left-hand operand is the
calling object. Writing c1 + c2 internally calls [Link]+(c2).
Eg: Overloading using friend function
#include <iostream>
using namespace std;
4 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
class Complex {
float real;
float imag;
public:
// Constructor
Complex(float r = 0, float i = 0) {
real = r;
imag = i;
}
// Friend function declaration
friend Complex operator+(Complex c1, Complex c2);
// Display function
void display() {
cout << real << " + " << imag << "i" << endl;
}
};
// Friend function definition
Complex operator+(Complex c1, Complex c2) {
Complex temp;
[Link] = [Link] + [Link]; // Add real parts
[Link] = [Link] + [Link]; // Add imaginary parts
return temp;
}
int main() {
Complex c1(3.5, 2.5);
Complex c2(1.6, 4.2);
Complex c3;
c3 = c1 + c2; // Calls friend operator+()
cout << "First Complex Number: ";
[Link]();
cout << "Second Complex Number: ";
[Link]();
cout << "Sum of Complex Numbers: ";
[Link]();
return 0;
}
Inheritance
The capability of a class to derive properties and characteristics from another class is
called Inheritance. Inheritance is one of the most important features of Object-Oriented Programming
in C++.
Sub Class: The class that inherits properties from another class is called Sub class or Derived Class.
Super Class:The class whose properties are inherited by sub class is called Base Class or Super class.
Syntax:
class DerivedClass : mode_of_inheritance BaseClass {
// Body of the Derived Class
};
where mode of inheritance controls the access level of the inherited members of the base class in the
derived class.
5 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
Modes of Inheritance
1. Public mode: If we derive a sub class from a public base class. Then the public member of the base
class will become public in the derived class and protected members of the base class will become
protected in derived class.
2. Protected mode: If we derive a sub class from a Protected base class. Then both public member and
protected members of the base class will become protected in derived class.
3. Private mode: If we derive a sub class from a Private base class. Then both public member and
protected members of the base class will become Private in derived class.
Note: The private members in the base class cannot be directly accessed in the derived class, while
protected members can be directly accessed.
Types Of Inheritance in C++
The inheritance can be classified on the basis of the relationship between the derived class and the
base class. In C++, we have 5 types of inheritances:
Single inheritance
Multilevel inheritance
Multiple inheritance
Hierarchical inheritance
Hybrid inheritance
1. Single Inheritance
In single inheritance, a class is allowed to inherit from only one class. i.e. one base class is inherited
by one derived class only.
Eg:
#include <iostream>
using namespace std;
// Base class
class Person {
public:
string name;
int age;
void getPersonData(string n, int a) {
6 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
name = n;
age = a;
}
void displayPersonData() {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
}
};
// Derived class
class Student : public Person {
public:
int rollNo;
float marks;
void getStudentData(int r, float m) {
rollNo = r;
marks = m;
}
void displayStudentData() {
cout << "Roll No: " << rollNo << endl;
cout << "Marks: " << marks << endl;
}
};
int main() {
Student s;
// Set data for base class
[Link]("John", 20);
// Set data for derived class
[Link](101, 88.5);
// Display base class data
[Link]();
// Display derived class data
[Link]();
return 0;
}
Since the class Student is inherited publicly from the Person class it will have the features of both the
Person class and the Student class.
2. Multiple Inheritance
Multiple Inheritance is a feature of C++ where a class can inherit from more than one class. i.e
one subclass is inherited from more than one base class.
Eg:
#include <iostream>
using namespace std;
7 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
// Base class 1
class Sports {
public:
int score;
void setScore(int s) {
score = s;
}
};
// Base class 2
class Academics {
public:
float marks;
void setMarks(float m) {
marks = m;
}
};
// Derived class inheriting from both Sports and Academics
class Student : public Sports, public Academics {
public:
string name;
void setName(string n) {
name = n;
}
void display() {
cout << "Name: " << name << endl;
cout << "Sports Score: " << score << endl;
cout << "Academic Marks: " << marks << endl;
}
};
int main() {
Student s;
[Link]("Amit");
[Link](85); // From Sports
[Link](92.5); // From Academics
[Link]();
return 0;
}
In this example, multiple inheritance is used where the class Student inherits publicly from
two base classes: Sports and Academics. The Sports class contains a data member score and a function
setScore() to set the sports score of a student. The Academics class contains a data member marks and
a function setMarks() to set academic marks. The derived class Student adds its own data member
name and a function display() to show all the information. By inheriting from both base classes,
Student can store and display both sports and academic achievements, showing how multiple
inheritance can combine distinct attributes and behaviours into a single object.
3. Multilevel Inheritance
8 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
In multilevel inheritance, a derived class is created from another derived class and that derived class
can be derived from a base class or any other derived class. There can be any number of levels.
Eg:
#include <iostream>
using namespace std;
// Base class
class Person {
public:
string name;
int age;
void setPersonData(string n, int a) {
name = n;
age = a;
}
void displayPersonData() {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
}
};
// Derived class from Person
class Student : public Person {
public:
int rollNo;
void setStudentData(int r) {
rollNo = r;
}
void displayStudentData() {
cout << "Roll No: " << rollNo << endl;
}
};
// Derived class from Student (third level)
class Graduate : public Student {
public:
string degree;
9 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
void setGraduateData(string d) {
degree = d;
}
void displayGraduateData() {
cout << "Degree: " << degree << endl;
}
};
int main() {
Graduate g;
// Set data from all levels
[Link]("Rahul", 22); // From Person
[Link](101); // From Student
[Link]("MCA"); // From Graduate
// Display data from all levels
[Link]();
[Link]();
[Link]();
return 0;
}
In multilevel inheritance, a class is derived from another class, which is itself derived from a
third class, forming a chain of inheritance. In this example, the base class Person contains general
details like name and age. The class Student inherits from Person and adds rollNo for student-specific
data. Finally, the class Graduate inherits from Student and adds degree for graduate-specific
information. An object of Graduate can access and use members from all three classes, demonstrating
how data and behaviour are passed down through multiple levels in the inheritance hierarchy.
4. Hierarchical Inheritance
In hierarchical inheritance, more than one subclass is inherited from a single base class. i.e. more than
one derived class is created from a single base class.
Eg:
#include <iostream>
using namespace std;
// Base class
class Person {
public:
string name;
int age;
void setPersonData(string n, int a) {
name = n;
age = a;
10 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
void displayPersonData() {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
}
};
// Derived class 1
class Student : public Person {
public:
int rollNo;
void setStudentData(int r) {
rollNo = r;
}
void displayStudentData() {
cout << "Roll No: " << rollNo << endl;
}
};
// Derived class 2
class Teacher : public Person {
public:
string subject;
void setTeacherData(string s) {
subject = s;
}
void displayTeacherData() {
cout << "Subject: " << subject << endl;
}
};
int main() {
Student s;
Teacher t;
// For Student object
[Link]("Amit", 20);
[Link](101);
cout << "Student Details:" << endl;
[Link]();
[Link]();
cout << endl;
// For Teacher object
[Link]("Meera", 35);
[Link]("Mathematics");
cout << "Teacher Details:" << endl;
11 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
[Link]();
[Link]();
return 0;
}
In hierarchical inheritance, multiple derived classes are created from a single base class. In
this example, Person is the base class containing common attributes like name and age. Two classes,
Student and Teacher, inherit from Person. The Student class adds a data member rollNo, and the
Teacher class adds a data member subject. This allows both derived classes to share the common
properties from Person while having their own specific properties. Hierarchical inheritance is useful
when different classes need the same common base features but also need to maintain their own
unique attributes.
5. Hybrid Inheritance
Hybrid Inheritance is implemented by combining more than one type of inheritance. For
example: Combining Hierarchical inheritance and Multiple Inheritance will create hybrid inheritance
in C++.
There is no particular syntax of hybrid inheritance. We can just combine two of the above inheritance
types. Below image shows one of the combinations of hierarchical and multiple inheritances:
Eg:
#include <iostream>
using namespace std;
// Base class
class Person {
public:
string name;
int age;
void setPersonData(string n, int a) {
name = n;
age = a;
}
void displayPersonData() {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
}
};
// Derived class 1 (Single inheritance from Person)
class Student : public Person {
public:
int rollNo;
12 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
void setStudentData(int r) {
rollNo = r;
}
void displayStudentData() {
cout << "Roll No: " << rollNo << endl;
}
};
// Another base class
class Sports {
public:
int score;
void setScore(int s) {
score = s;
}
void displayScore() {
cout << "Sports Score: " << score << endl;
}
};
// Derived class from Student and Sports (Multiple Inheritance)
class Scholar : public Student, public Sports {
public:
void displayAll() {
displayPersonData();
displayStudentData();
displayScore();
}
};
int main() {
Scholar sc;
[Link]("Amit", 20); // From Person (through Student)
[Link](101); // From Student
[Link](85); // From Sports
cout << "Scholar Details:" << endl;
[Link]();
return 0;
}
Hybrid inheritance is a combination of two or more types of inheritance, such as single,
multiple, multilevel, or hierarchical. In this example, we combine single inheritance and multiple
inheritance. First, Student inherits from Person (single inheritance). Then, Scholar inherits from both
Student and Sports (multiple inheritance). This hybrid approach allows the Scholar class to have
attributes from Person (name, age), Student (rollNo), and Sports (score) all in one object. Hybrid
inheritance is useful for modeling real-world entities that require features from different inheritance
types, but it must be used carefully to avoid ambiguities like the diamond problem.
13 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
Virtual Base Class
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. Consider the
situation where we have one class A . This class A is inherited by two other classes B and C. Both
these classes are inherited into another in a new class D as shown in figure below.
As we can see from the figure that data members/function of class A are inherited twice to
class D. One through class B and second through class C. When any data / function member of
class A is accessed by an object of class D, ambiguity arises as to which data/function member would
be called? One inherited through B or the other inherited through C. This confuses compiler and it
displays error. This is called the Diamond Problem.
To resolve this ambiguity when class A is inherited in both class B and class C, it is declared
as virtual base class by placing a keyword virtual as:
Syntax 1:
class B : virtual public A
{
};
Syntax 2:
class C : public virtual A
{
};
Now only one copy of data/function member will be copied to class C and class B and
class A becomes the virtual base class. Virtual base classes offer a way to save space and avoid
ambiguities in class hierarchies that use multiple inheritances. When a base class is specified as a
virtual base, it can act as an indirect base more than once without duplication of its data members. A
single copy of its data members is shared by all the base classes that use virtual base.
Eg:
#include <iostream>
using namespace std;
// Base class
class Person {
public:
string name;
void setName(string n) {
name = n;
}
};
// Derived class 1 (virtual inheritance)
class Student : virtual public Person {
14 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
public:
int rollNo;
void setRollNo(int r) {
rollNo = r;
}
};
// Derived class 2 (virtual inheritance)
class Teacher : virtual public Person {
public:
string subject;
void setSubject(string s) {
subject = s;
}
};
// Derived class from both Student and Teacher
class Scholar : public Student, public Teacher {
public:
void display() {
cout << "Name: " << name << endl;
cout << "Roll No: " << rollNo << endl;
cout << "Subject: " << subject << endl;
}
};
int main() {
Scholar sc;
[Link]("Amit"); // From Person (only one copy shared)
[Link](101); // From Student
[Link]("Math"); // From Teacher
[Link]();
return 0;
}
In the above example, both Student and Teacher inherit from Person. Without the virtual
keyword, the Scholar class (which inherits from both Student and Teacher) would contain two
separate copies of Person’s data, causing ambiguity when accessing name. By declaring Person as a
virtual base class in both Student and Teacher, only one shared copy of Person’s members exists in
Scholar. This removes ambiguity and ensures data consistency when accessing members of the
common base class.
Pure Virtual Functions and Abstract Class
A pure virtual function is a special type of virtual function in C++ that does not have any
definition in the base class and is meant to be overridden in derived classes. It acts as a placeholder for
functions that must be implemented by the derived classes. A pure virtual function is declared by
assigning = 0 at the end of its declaration inside the base class. For example:
virtual void display() = 0;
15 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
By making a function pure virtual, the compiler ensures that no objects of the base class can be
created directly, as the function has no implementation there. This feature is used when the base class
defines a general interface, but the actual functionality should be provided by its derived classes.
An abstract class in C++ is a class that contains at least one pure virtual function. It cannot be
instantiated directly, meaning you cannot create objects of an abstract class. However, it can be used to
create pointers or references to point to objects of derived classes. Abstract classes are often used as
interfaces in object-oriented programming, defining a common contract for all derived classes. They
may also have normal (fully defined) member functions and data members, but if even one pure
virtual function is present, the class is considered abstract.
The main purpose of pure virtual functions and abstract classes is to achieve run time
polymorphism and code reusability. They allow you to write code that works with different derived
classes through a common base class interface. This is particularly useful when different derived
classes have similar behaviour but require different implementations for certain operations. For
example, in a Shape base class, the function area() can be declared as a pure virtual function, and
different derived classes like Circle and Rectangle can provide their own implementations for
calculating the area.
Declared using virtual return_type functionName() = 0; inside a base class.
A class with at least one pure virtual function is automatically an abstract class.
Abstract classes cannot be instantiated but can be used as pointers or references.
All derived classes must override all pure virtual functions to become concrete classes (classes that
can be instantiated).
Useful for designing interfaces and achieving runtime polymorphism.
Eg:
#include <iostream>
using namespace std;
// Abstract base class
class Shape {
public:
// Pure virtual function
virtual void area() = 0;
// Normal member function
void displayType() {
cout << "This is a shape." << endl;
}
};
// Derived class 1
class Circle : public Shape {
float radius;
public:
Circle(float r) : radius(r) {}
// Overriding pure virtual function
void area() override {
cout << "Area of Circle: " << 3.14 * radius * radius << endl;
}
};
16 Sunandha Rajagopal
Introduction to Object Oriented Programming Module-3
// Derived class 2
class Rectangle : public Shape {
float length, breadth;
public:
Rectangle(float l, float b) : length(l), breadth(b) {}
// Overriding pure virtual function
void area() override {
cout << "Area of Rectangle: " << length * breadth << endl;
}
};
int main() {
Shape* shapePtr; // Pointer to base abstract class
Circle c(5);
Rectangle r(4, 6);
shapePtr = &c; // Pointing to Circle object
shapePtr->displayType();
shapePtr->area();
shapePtr = &r; // Pointing to Rectangle object
shapePtr->displayType();
shapePtr->area();
return 0;
}
Shape is an abstract base class because it contains a pure virtual function area(). The pure
virtual function is declared using = 0, which means it has no body in the base class. The Circle and
Rectangle classes inherit from Shape and provide their own implementation for area(). We cannot
create an object of Shape directly, but we can use a pointer to Shape to achieve runtime
polymorphism. The same base class pointer (shapePtr) is used to call area() for both Circle and
Rectangle, and the correct version runs depending on the object it points to.
17 Sunandha Rajagopal