MOD 3 Stdi
MOD 3 Stdi
C++ Module -3
MODULE – 3
Operator Overloading
class A
{
statements;
};
int main()
{
A a1, a2, a3;
a3 = a1 + a2;
return 0;
}
In this example, we have 3 variables “a1”, “a2” and “a3” of type “class A”. Here we are trying to
add two objects “a1” and “a2”, which are of user-defined type i.e. of type “class A” using the
“+” operator. This is not allowed, because the addition operator “+” is predefined to operate only
on built-in data types. But here, “class A” is a user-defined type, so the compiler generates an
error. This is where the concept of “Operator overloading” comes in.
Now, if the user wants to make the operator “+” add two class objects, the user has to redefine
the meaning of the “+” operator such that it adds two class objects. This is done by using the
concept of “Operator overloading”. So the main idea behind “Operator overloading” is to use
C++ operators with class variables or class objects. Redefining the meaning of operators really
does not change their original meaning; instead, they have been given additional meaning along
with their existing ones.
In C++, you can overload a variety of operators, including arithmetic operators, comparison
operators, assignment operators, logical operators, and more.
In order to use operator overloading we have to define operator function i.e either
member function or friend function
a. Unary Operator
Syntax as member function :-
}
If unary operator is overloaded using friend one argument is needed
b. Binary Operator
Syntax as member function :-
}
If binary operator is overloaded using member function one argument is needed.
Syntax as Friend function :-
#include<iostream.h>
#include<conio.h>
using namespace std;
class complex
{
int a, b, c;
public:
complex( )
{
void getvalue( )
{
cout << "Enter the Two Numbers:";
cin >> a>>b;
}
void operator++( )
{
a = ++a;
b = ++b;
}
void operator--( )
{
a = --a;
b = --b;
}
void display( )
{
cout << a << "+\t" << b << "i" << endl;
}
};
void main( )
{
clrscr( );
complex obj;
obj.getvalue();
obj++;
cout << "Increment Complex Number\n";
obj.display();
obj--;
cout << "Decrement Complex Number\n";
obj.display();
getch();
}
Sample Output :
Enter the two numbers: 3 6
Increment Complex Number
4+ 7i
Decrement Complex Number
3 + 6i
#include <iostream>
using namespace std;
class Arith_num
{
// declare data member or variable
int x, y;
public:
// create a member function to take input
void input()
{
cout << " Enter the first number: ";
cin >> x;
}
void input2()
{
cout << " Enter the second number: ";
cin >> y;
}
Output
In the above program, we take two numbers, 5 and 6, from the user and then overload the binary
plus (+) operator to perform the addition that returns the sum of two numbers is 11.
#include <iostream>
using namespace std;
class Complex
{
private:
int real;
int img;
public:
Complex (int r = 0, int i = 0)
{
real = r;
img = i;
}
void Display ()
{
cout << real << "+i" << img;
}
friend Complex operator + (Complex c1, Complex c2);
};
int main ()
{
Complex C1(5, 3), C2(10, 5), C3;
C1.Display();
cout << " + ";
C2.Display();
cout << " = ";
C3 = C1 + C2;
C3.Display();
}
In the above example, we have created two integer type private data members real and img.
Then we overloaded the + operator with two parameters C1 and C2. We have not defined
the body here. We have made it a friend by using the friend function. This is the prototype
of the friend function in C++. This function will return an object of type Complex. So, this
friend function will take two complex numbers as parameters and return a Complex number.
C3 = C1 + C2;
It is just like there is a function that will take C1 and C2 as parameters and add them and
return the result. So, neither C1 nor C2 adding but someone else is adding. This friend
function has to be written outside the class without using scope resolution. Now let us write
the body of the friend function ‘operator +’ outside the class,
The new and delete operators can also be overloaded like other operators in C++. New and
Delete operators can be overloaded globally or they can be overloaded for specific classes.
If these operators are overloaded using member function for a class, it means that these operators
are overloaded only for that specific class.
If overloading is done outside a class (i.e. it is not a member function of a class), the overloaded
‘new’ and ‘delete’ will be called anytime you make use of these operators (within classes or
outside classes). This is global overloading.
The overloaded new operator receives size of type size_t, which specifies the number of bytes of
memory to be allocated. The return type of the overloaded new must be void*.The overloaded
function returns a pointer to the beginning of the block of memory allocated.
The function receives a parameter of type void* which has to be deleted. Function should not
return anything.
NOTE: Both overloaded new and delete operator functions are static members by default.
Therefore, they don’t have access to this pointer .
Overloading new and delete operator for a specific class:
// program to demonstrate Overloading new and delete operator for a specific class
#include<iostream>
#include<stdlib.h>
{
cout<< "Constructor is called\n" ;
}
student(string name, int age)
{
this->name = name;
this->age = age;
}
void display()
{
cout<< "Name:" << name << endl;
cout<< "Age:" << age << endl;
}
void * operator new(size_t size)
{
cout<< "Overloading new operator with size: " << size << endl;
void * p = ::operator new(size);
//void * p = malloc(size); will also work fine
return p;
}
int main()
{
student * p = new student("Yash", 24);
p->display();
delete p;
return 0;
}
Output
Overloading new operator with size: 40
Name:Yash
Age:24
Overloading delete operator
NOTE:
In the above new overloaded function, we have allocated dynamic memory through new
operator, but it should be global new operator otherwise it will go in recursion
void *p = new student(); // this will go in recursion as new will be overloaded again and again
void *p = ::new student(); // this is correct
#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
int n = 5, i;
int * p = new int[n];
delete [] p;
return 0;
}
Output
New operator overloading
Array: 0 1 2 3 4
Delete operator overloading
NOTE: In the code above, in new overloaded function we cannot allocate memory
using ::new int[5] as it will go in recursion. We need to allocate memory using malloc only.
1. The overloaded new operator function can accept arguments; therefore, a class can have
multiple overloaded new operator functions. This gives the programmer more flexibility in
customizing memory allocation for objects.
For example:
3. Overloaded new or delete operators also provide Garbage Collection for class’s object.
INHERITANCE
2. The Members of one Class can be accumulated in another Class through Inheritance.
3. The Class which acts as the source of providing its Members for Inheritance is
called the Parent or Base Class. The Class that derives from or acquires the
Members of Base Class is called the Child or Derived Class.
4. The Private members of any Class can Not be Inherited.
1) Public Inheritance :- Here the Child Class acquires the Protected and
Public Members. And they Remain Protected and Public in the Child Class.
Its done by using “public “ keyword during Child Class definition.
Syntax :-
class child-class-name : public parent-class-name
{
definition of the child class
};
2) Private Inheritance :- Here the Child Class acquires the Protected and
Public Members. And they Become Private in the Child Class. Its done by
using “private “ keyword during Child Class definition.
Syntax :-
class child-class-name : private parent-class-name
{
definition of the child class
};
3) Protected Inheritance :- Here the Child Class acquires the Protected and
Public Members. And they Become Protected in the Child Class. Its done
by using “protected “ keyword during Child Class definition.
Syntax :-
3) Multiple Inheritance
4) Hierarchical Inheritance
5) Hybrid Inheritance
Syntax :-
class child-class-name : <access-mode> parent-class-name
{
definition code for the child class
};
Example :
class A
{
public:
void display()
{
cout<<”\n class A display called”;
}
};
class B : public A
{
public :
void display()
{
cout<<”\n class B display called”;
}
};
int main()
{
B obj;
obj.display();
obj.A::display();
return 0;
}
Example :
class A
{
public:
void display()
{
cout<<”\n class A display called”;
}
};
class B : public A
{
public :
void display()
{
cout<<”\n class B display called”;
}
};
gets created for every Object created from the Child Class.
2) As an Instance of the Parent Class is created, so the constructor of the
we need to call the Grand Parent class constructor through the Grand Child
class constructor and also the usual calling of immediate parent class
constructor by immediate child class constructor also needs to be followed.
If Virtual Base class is not used then the grand child can not call the grand
parent class constructor.
7) The Destructors are called in the just the Reverse order in which the
Example :
class A
{
int a;
public:
A(int z)
{
cout<<"\nParameterized Constructor of Class A Called";
a=z;
}
A(int u, int v)
{
cout<<"\nOverloaded Parameterized Contructor of Class A Called";
}
void show()
{
cout<<"\n"<<a;
}
};
class B:public A
{
int b;
public:
B(int z):A(z) //Parent class A constructor getting invoked with parameter
{
cout<<"\nParameterized Constructor of Class B Called";
b=z;
}
void show()
{
cout<<"\n"<<b;
}
};
class C:public B
{
int c;
public:
C():B(0) //Parent class A constructor getting invoked with parameter
{
c=0;
cout<<"\nDefault Constructor of Class C Called";
}
C(int z):B(z) //Parent class A constructor getting invoked with parameter
{
cout<<"\nParameterized Constructor of Class C Called"; c=z;
}
void show()
{
cout<<"\n"<<c;
}
};
int main()
{
C ob;
ob.A::show();
ob.B::show();
ob.show();
C ob2(10);
ob2.A::show();
ob2.B::show();
ob2.show();
return 0;
}
Example :
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void sound()
{
cout << "Animal sound" << endl;
}
};
};
};
int main()
{
Bat bat;
In this example:
Animal is the virtual base class. Mammal and Bird are two classes that inherit virtually from
Animal. Bat is a class that inherits from both Mammal and Bird.
By using the virtual keyword when inheriting, you ensure that there is only one instance of the
Animal subobject shared among the Mammal and Bird subobjects within the Bat class. This
avoids the duplication of the Animal subobject, which is a common issue in multiple inheritance
scenarios.
The virtual inheritance helps prevent ambiguity and ensures that there is a single path to reach
the virtual base class in the class hierarchy.