Module 3-1 Oops
Module 3-1 Oops
Module 3-1 Oops
with C++(BCS306B)
Module – 3
Chapter 1 :
OPERATOR OVERLOADING :
SYLLABUS:
Operator Overloading: Creating a Member Operator Function, Operator Overloading Using a Friend Function, Overloading new
By,
and delete. Inheritance: Base-Class Access Control, Inheritance and Protected Members, Inheriting Multiple Base Classes ,
Constructors, Destructors and Inheritance, Granting Access, Virtual Base Classes.
Dr. Madhu B.G.
Associate Professor, Department of CS&E
AIT, Chikkamagaluru - 577102
Website:vtucode.in
Email : [email protected]
[email protected]
Mobile: 9611699567
C++ Operator Overloading :
int a;
float b,sum;
sum = a + b;
Here, variables “a” and “b” are of types “int” and “float”, which are built-in
data types. Hence the addition operator ‘+’ can easily add the contents of “a”
and “b”.
This is because the addition operator “+” is predefined to add variables of
built-in data type only.
// C++ Program to Demonstrate the working/Logic behind 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.
3.1 Creating a Member Operator Function
Operator overloading is the process of making an operator exhibit different
behaviors in different instances.
Ways of operator overloading
1) Operator overloading of member functions.
2) Operator overloading of non-member or friend functions.
Here,
returnType is the return type of the function.
the operator is a keyword.
the symbol is the operator that we want to overload. Like: +, <, -, ++, etc.
arguments are the arguments passed to the function.
Complete Example to add two Complex Numbers in C++:
#include<iostream>
using namespace std;
class Complex
{
private:
int real;
int img;
public:
Complex (int r = 0, int i = 0)
{
real = r;
img = i;
}
Complex add (Complex x)
{
Complex temp;
temp.real = real + x.real;
temp.img = img + x.img;
return temp;
}
void Display() {
cout << real << "+i" << img <<endl;
}
};
int main()
{
Complex C1 (3, 7);
C1.Display();
Complex C2 (5, 2);
C2.Display();
Complex C3;
C3 = C1.add (C2); // C2.add(C1);
C3.Display();
}
OUTPUT :
Example to add two Complex Numbers in C++ using Operator Overloading:
#include<iostream>
using namespace std;
class Complex
{
private:
int real;
int img;
public:
Complex (int r = 0, int i = 0)
{
real = r;
img = i;
}
Complex operator + (Complex x)
{
Complex temp;
temp.real = real + x.real;
temp.img = img + x.img;
return temp;
}
void Display() {
cout << real << "+i" << img <<endl;
}
};
int main ()
{
Complex C1(5, 3), C2(10, 5), C3;
C1.Display();
cout << " + ";
C2.Display();
cout << " = ";
C3 = C1 + C2;
C3.Display();
}
OUTPUT:
5+i3 + 10+i5 = 15+i8
3.3 Overloading new and delete
The new operator allocates memory to a variable. For example,
// declare an int pointer
int* pointVar;
// dynamically allocate memory using the new keyword
pointVar = new int;
// assign value to allocated memory
*pointVar = 45;
Here, we have dynamically allocated memory for an int variable using the new
operator.
Notice that we have used the pointer pointVar to allocate the memory dynamically.
This is because the new operator returns the address of the memory location.
In the case of an array, the new operator returns the address of the first element of
the array.
From the example above, we can see that the syntax for using the new operator is
pointerVariable = new dataType;
delete Operator
Once we no longer need to use a variable that we have declared dynamically, we
can deallocate the memory occupied by the variable.
For this, the delete operator is used. It returns the memory to the operating
system. This is known as memory deallocation.
delete pointerVariable;
The general form of operator overloading new
The general form of overloading the new operator is as follows:
here
•return_type is a type (class) to which the operator function returns a pointer for
which memory is allocated by a special (non-standard method);
•size – size of memory that is allocated for return_type type.
(size_t is essentially an unsigned integer.) The parameter size will contain the
number of bytes needed to hold the object being allocated.
The general form of operator overload delete
The general form of operator overload delete is as follows:
void operator delete(void * pointer)
{
// freeing the memory pointed to by the pointer pointer
// ...
}
here pointer – a pointer to the memory area that was previously allocated by the
operator new.
Why overload new and delete?
You might choose to do this if you want to use some special allocation method.
For example, you may want allocation routines that automatically begin using a
disk file as virtual memory when the heap has been exhausted.
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.
#include <iostream>
using namespace std;
class MyClass
{
int num;
public:
MyClass()
{
}
MyClass(int a):num(a)
{
}
void display()
{
cout<< "num:" << num << endl;
}
void * operator new(size_t size)
{
cout<< "Overloading new operator with size: " << size
<< endl;
void * p = ::new MyClass();
//void * p = malloc(size); will also work fine
return p;
}
void operator delete(void * p)
{
cout<< "Overloading delete operator " << endl;
free(p);
size_t is a special unsigned integer type defined in
}
}; the standard library of C and C++.
The size_t is chosen so that it can store the
int main()
maximum size of a theoretically possible.arr or an
{
MyClass * p = new MyClass(24);
p->display();
delete p;
}
OUTPUT:
INHERITANCE:
3.4 Base-Class Access Control
When a class inherits another, the members of the base class become members
of the derived class. Class inheritance uses this general form:
The access status of the base-class members inside the derived class is
determined by access. The base-class access specifier must be either public,
private, or protected.
If no access specifier is present, the access specifier is private by default if
the derived class is a class. If the derived class is a struct, then public is the
default in the absence of an explicit access specifier.
When the access specifier for a base class is public, all public members of
the base become public members of the derived class, and all protected
members of the base become protected members of the derived class.
In all cases, the base's private elements remain private to the base and are
not accessible by members of the derived class.
In C++ inheritance, we can derive a child class from the base class in different
access modes. For example,
class Base
{
.... ... ....
};
int main()
{
PublicDerived object1;
cout << "Private = " << object1.getPVT() << endl;
cout << "Protected = " << object1.getProt() << endl;
cout << "Public = " << object1.pub << endl;
return 0;
}
Output :
Private = 1
Protected = 2
Public = 3
Here, we have derived PublicDerived from Base in public mode.
As a result, in PublicDerived:
•prot is inherited as protected.
•pub and getPVT() are inherited as public.
•pvt is inaccessible since it is private in Base.
Since private and protected members are not accessible, we need to create
public functions getPVT() and getProt() to access them:
3.5 Inheritance and Protected Members
Protected mode – If the derived class inherits the properties of the base class
in protected mode, then both public and protected members will
become protected in the derived class.
/* Program to show the Protected Inheritance */
#include<iostream>
using namespace std; /* Base Class */
class Base
{
protected:
int b=2;
private:
int c=3;
public:
int a=1;
// Function to access private data member of the class
int getPrivate()
{
return c;
}
};
/* Derived Class is inheriting the Base Class protectedly*/
class Derived: protected Base
{
public:
// Function to access the public value of the base class
int getPublic()
{
return a;
}
// Function to access the protected value of the base class
int getProtected()
{
return b;
}
};
int main() /* Driver Function */
{
Derived obj;
cout<<"Public member for the given class is:
"<<obj.getPublic()<<endl;
cout<<"Private members are not accessible in the
derived class"<<endl;
cout<<"Protected member for the given class is:
"<<obj.getProtected()<<endl;
return 0;
}
{
// code of the derived class
}
In the above syntax, class A and class B are two base classes, and class C is the
child class that inherits some features of the parent classes.
Example 1: Program to use the Multiple Inheritance
#include <iostream>
using namespace std;
Output :
It is the first function of the Base class
It is the second function of the Base class
It is the function of the derived class
3.7 Constructors
Constructor in C++ is a special method that is invoked automatically at the
time of object creation. It is used to initialize the data members of new objects
generally. The constructor in C++ has the same name as the class or structure.
To create a constructor,
use the same name as the class, followed by parentheses ():
int main() {
MyClass myObj; // Create an object of MyClass (this
will call the constructor)
return 0;
}
Output:
Hello World
// Example: defining the constructor within the class
#include<iostream>
using namespace std;
class student
{
int rno;
char name[50];
double fee;
public:
student()
{
cout<<"Enter the RollNo:";
cin>>rno;
cout<<"Enter the Name:";
cin>>name;
cout<<"Enter the Fee:";
cin>>fee;
}
void display()
{
cout<<endl<<rno<<"\t"<<name<<"\t"<<fee;
}
};
int main()
{
student s; //constructor gets called automatically
when we create the object of the class
s.display();
return 0;
OutPut:
Enter the RollNo:Enter the Name:Enter the Fee: 2 0
Example: defining the constructor outside the class
#include<iostream>
using namespace std;
class student
{
int rno;
char name[50];
double fee;
public:
student();
void display();
};
student::student()
{
cout<<"Enter the RollNo:";
cin>>rno;
cout<<"Enter the Name:";
cin>>name;
cout<<"Enter the Fee:";
cin>>fee;
}
void student::display()
{
cout<<endl<<rno<<"\t"<<name<<"\t"<<fee;
}
int main()
{
student s;
s.display();
return 0;
}
Output:
~parent() //destructor
{
cout << "Parent class Destructor\n";
}
};
class child : public parent //child class
{
public:
child() //constructor
{
cout << "Child class Constructor\n";
}
~ child() //destructor
{
cout << "Child class Destructor\n";
}
};
int main()
{
//automatically executes both child and parent class
//constructors and destructors because of inheritance
child c;
return 0;
}
Output :
base-class::member;
class base {
public: // public in base
int j;
};
class derived: private base // Inherit base as private.
{
public: // here is access declaration
base::j; // make j public again // ...
};
Because base is inherited as private by derived, the public variable j is made a
private variable of derived.
Because base is inherited as private by derived, the public member j is
made a private member of derived. However, by including
base::j;
as the access declaration under derived's public heading, j is restored to
its public status.
You can use an access declaration to restore the access rights of public and
protected members. However, you cannot use an access declaration to raise
or lower a member's access status.
For example, a member declared as private in a base class cannot be made
public by a derived class.
in C++, While granting access demoting a variable from protected to public is
not allowed but it is happening.
#include<iostream>
using namespace std;
class base {
protected: int x; // x is protected
};
Output :
a = 10