Unit-5 1
Unit-5 1
int main() {
Demo obj1; // Default Constructor
obj1.display();
return 0;
}
Output:
Default Constructor Called
x: 0, y: 0
Parameterized Constructor Called
x: 10, y: 20
Copy Constructor Called
x: 10, y: 20
Operator Overloading
In C++, Operator overloading is a compile-time polymorphism.
For example, we can overload an operator ‘+’ in a class like String so that we can concatenate
two strings by just using +. Other example classes where arithmetic operators may be
overloaded are Complex Numbers, Fractional Numbers, Big integers, etc.
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.
// Operator Overloading
#include <iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0)
{
real = r;
imag = i;
}
// This is automatically called when '+' is used with between two Complex objects
Complex operator+(Complex const& obj)
{
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << '\n'; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
}
Output
12 + i9
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 behavior 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. Overloaded conversion operators must be a member method. Other
operators can either be the member method or the global method.
4) Any constructor that can be called with a single argument works as a conversion
constructor, which means it can also be used for implicit conversion to the class being
constructed
Note: private members of the base class are inaccessible to the derived class.
class Base {
private:
int pvt = 1;
protected:
int prot = 2;
public:
int pub = 3;
int getPVT() {
return pvt;
};
public:
int getProt() {
return prot;
};
int main() {
PublicDerived object1;
return 0;
Output
Private = 1
Protected = 2
Public = 3
As a result, in PublicDerived:
int main() {
ProtectedDerived object1;
cout << "Private cannot be accessed." << endl;
cout << "Protected = " << object1.getProt() << endl;
cout << "Public = " << object1.getPub() << endl;
return 0;
}
Run Code
Output
#include <iostream>
class Base {
private:
int pvt = 1;
protected:
int prot = 2;
public:
int pub = 3;
// function to access private member
int getPVT() {
return pvt;
};
public:
int getProt() {
return prot;
int getPub() {
return pub;
};
int main() {
PrivateDerived object1;
return 0;
Run Code
Output
Protected = 2
Public = 3
As a result, in PrivateDerived:
As we know, private members cannot be directly accessed from outside the class. As a result, we
cannot use getPVT() from PrivateDerived.
That is also why we need to create the getPub() function in PrivateDerived in order to access
the pub variable.
private
Accessibility protected members public members
members
The best Real-life example of this concept is the Constitution of India. India took the political code,
structure, procedures, powers, and duties of government institutions and set out fundamental rights,
directive principles, and the duties of citizens of other countries and implemented them on its own;
making it the biggest constitution in the world.
Another Development real-life example could be the relationship between RBI(The Reserve Bank of
India) and Other state banks like SBI, PNB, ICICI, etc. Where the RBI passes the same regulatory
function and others follow it as it is.
In compile time function overriding, the function call and the definition is binded at the compilation
of the program. Due to this, it is also called early binding or static binding.
class Parent {
access_modifier :
// overridden function
return_type name_of_the_function() {}
};
access_modifier :
// overriding function
return_type name_of_the_function() {}
};
Unlike other languages like Java, the function overriding in C++ can be performed at both compile
time and runtime. In all the above examples, the call to the overridden function is resolved during
compile time. It is also called early binding where the function call is binded to its definition during
compilation.
Function overriding can also be performed at the runtime, which means that function call will be
binded to its definition during runtime (also known as late binding or dynamic binding). This can be
done with the help of virtual functions.
class Base {
public:
virtual func()
// definition
};
public:
func() override
// new definition
};
Here, override keyword tells the compiler that the given overridden function should be declared as
virtual in the parent class. It is a kind of double check as the program can compile without errors
even if the function is not virtual. But then, it will be compile time polymorphism and we won’t get
the desired behaviour of the function overriding.
Need for Virtual Base Classes: Consider the situation where we have one class A . This class A is
inherited by two other classes B and C. Both these class 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.
#include <iostream>
class A {
public:
int a;
A() // constructor
a = 10;
};
};
};
int main()
return 0;
Pointer
Pointers are symbolic representation of addresses. The pointer in C++ language is a variable, it is also
known as locator or indicator that points to an address of a value.
Syntax:
Here the variable being declared is a pointer, pointing to a constant integer. Effectively, this implies
that the pointer is pointing to a value that shouldn’t be changed. Const qualifier doesn’t affect the
pointer in this scenario so the pointer is allowed to point to some other address.
Syntax:
Or
Array of Objects
An array of objects in C++ is a collection of objects of the same class. It allows you to manage multiple
objects efficiently, just as arrays help manage collections of primitive data types.
An array of objects is used when you need to manage a collection of objects of the same class type.
Instead of creating multiple individual objects manually, an array allows you to:
3. Reduce redundancy and simplify code when dealing with a fixed number of objects.
An array of objects is suitable for scenarios where you have to manage a group of similar entities (eg:
Student Records), Fixed Number of Items (eg. Product Inventory), Processing Batch Operations.
#include <iostream>
class Product {
int id;
string name;
float price;
public:
id = pid;
name = pname;
price = pprice;
void displayDetails() {
cout << "ID: " << id << ", Name: " << name << ", Price: $" << price << endl;
};
int main() {
products[i].displayDetails();
return 0;
Output:
Product Inventory: