Class & Object with Constructors &
Destructors
• Constructor: Initializes an object automatically when it is created.
• Copy Constructor: Initializes a new object using an existing object.
• Destructor: Destroys an object and releases resources when it goes out of scope.
#include <iostream>
using namespace std;
class Student
{
private:
int rollNo;
string name;
public:
// Parameterized Constructor
Student(int rollNo, string name)
{
this->rollNo = rollNo;
this->name = name;
cout << "Parameterized Constructor called" << endl;
}
// Copy Constructor
Student(const Student &obj)
{
this->rollNo = [Link];
this->name = [Link];
cout << "Copy Constructor called" << endl;
}
// Member Function
void display()
{
cout << "Roll No: " << rollNo << endl;
cout << "Name: " << name << endl;
}
// Destructor
~Student()
{
cout << "Destructor called" << endl;
}
};
int main()
{
Student s1(101, "Rahul"); // Parameterized constructor
Student s2 = s1; // Copy constructor called
[Link]();
[Link]();
return 0; // Destructor called for both objects
}
O/P:-
Parameterized Constructor called
Copy Constructor called
Roll No: 101
Name: Rahul
Roll No: 101
Name: Rahul
Destructor called
Destructor called
Access specifiers (private, protected, public)
Templates
Problem, we require multiple add functions forhandling arguments of different data types
#include <iostream>
using namespace std;
// Add two integers
int add(int a, int b) {
return a + b;
}
// Add two doubles
double add(double a, double b) {
return a + b;
}
// Add two floats
float add(float a, float b) {
return a + b;
}
// Add two characters (ASCII addition)
int add(char a, char b) {
return a + b;
}
int main() {
int x = 10, y = 20;
double p = 3.5, q = 2.5;
float f1 = 1.1f, f2 = 2.2f;
char c1 = 'A', c2 = 'B';
cout << "Add integers: " << add(x, y) << endl;
cout << "Add doubles: " << add(p, q) << endl;
cout << "Add floats: " << add(f1, f2) << endl;
cout << "Add chars (ASCII): " << add(c1, c2) << endl;
}
Solution: Templates in C++
Templates allow writing generic and reusable code. Instead of writing the same code for multiple
data types, templates allow type-agnostic programming.
Function template Class template
#include <iostream> #include <iostream>
using namespace std; using namespace std;
// Function template to add two values of any template <typename T>
type class Box {
template <typename T> T content;
T add(T a, T b) { public:
return a + b; Box(T c) : content(c) {}
} void show() { cout << "Content: " << content
<< endl; }
int main() { };
int x = 10, y = 20;
double p = 3.5, q = 2.5; int main() {
float f1 = 1.1f, f2 = 2.2f; Box<int> intBox(123);
char c1 = 'A', c2 = 'B'; Box<double> doubleBox(45.67);
Box<string> strBox("Hello");
cout << "Add integers: " << add(x, y) << endl;
cout << "Add doubles: " << add(p, q) << endl; [Link]();
cout << "Add floats: " << add(f1, f2) << endl; [Link]();
cout << "Add chars (ASCII): " << add(c1, c2) [Link]();
<< endl; }
}
O/P:-
O/P:-
Add integers: 30 Content: 123
Add doubles: 6 Content: 45.67
Add floats: 3.3 Content: Hello
Add chars (ASCII): 131
.
Friend Functions
A friend function is a non-member function that has access to the private and protected members
of a class.
friend function
#include <iostream>
using namespace std;
class BankAccount {
string name;
double balance;
public:
BankAccount(string n, double b) : name(n), balance(b) {}
// Friend function declaration
friend void displayBalance(const BankAccount& account);
};
// Friend function definition
void displayBalance(const BankAccount& account) {
cout << "Account Holder: " << [Link] << endl;
cout << "Balance: $" << [Link] << endl;
}
int main() {
BankAccount acc("Alice", 5000);
displayBalance(acc); // Access private members
}
O/P:-
Account Holder: Alice
Balance: $5000
Inline Function
An inline function is a function where the compiler attempts to replace the function call
with the function code at compile time to reduce function call overhead.
Best for small, frequently called function, but Cannot be recursive
Ex:- inline int add(int a, int b) {
return a + b;
}
.
Polymorphism
Function & operator overloading
Compile-time polymorphism is achieved when the compiler decides which function to call based on
function signature.
Function Overloading
#include <iostream>
using namespace std;
class Math {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
int main() {
Math m;
cout << [Link](2, 3) << endl; // calls add(int, int)
cout << [Link](2.5, 3.5) << endl; // calls add(double, double)
cout << [Link](1, 2, 3) << endl; // calls add(int, int, int)
}
O/P:-
5
6
6
Operator Overloading
Giving user-defined meaning to operators (+, -, <<, etc.) for custom objects.
📌 Operators cannot be overloaded: ::, ., .*, sizeof
Operator Overloading
#include <iostream>
using namespace std;
class Complex {
int real, imag;
public:
Complex(int r = 0, int i = 0) {
real = r;
imag = i;
}
Complex operator + (const Complex& c) {
return Complex(real + [Link], imag + [Link]);
}
void show() {
cout << real << " + " << imag << "i" << endl;
}
};
int main() {
Complex c1(2, 3), c2(4, 5);
Complex c3 = c1 + c2; // compile-time polymorphism
[Link]();
}
O/P:-
6 + 8i
Function Overriding
class Shape {
public:
virtual double area() = 0;
};
class Rectangle : public Shape {
public:
double area() override {
return 10 * 5;
}
};
class Circle : public Shape {
public:
double area() override {
return 3.14 * 5 * 5;
}
};
Abstract Class
A class that contains a pure virtual function is known as an abstract class.
We cannot create objects of an abstract class. However, we can derive classes
from them, and use their data members and member functions (except pure
virtual functions)
Runtime (virtual functions)
A virtual function is a member function in the base class that can be overridden in
derived classes.
Virtual functions are a key part of polymorphism in C++.
Without Virtual Function With Virtual Function
class Animal { class Animal {
public: public:
void sound() { virtual void sound() {
cout << "Animal sound\n"; cout << "Animal sound\n";
} }
}; };
class Dog : public Animal { class Dog : public Animal {
public: public:
void sound() { void sound() override {
cout << "Dog barks\n"; cout << "Dog barks\n";
} }
}; };
int main() { int main() {
Animal* a Animal* a;
Dog d; Dog d;
a = &d; a = &d;
a->sound(); a->sound(); // Outputs: Dog
return 0; barks
} return 0;
// Call the sound() function }
using the pointer. Since sound()
is not virtual, this calls
Animal's version
Note:- The -> Operator in C++
The -> operator is used to access members (like functions or variables) through
a pointer.
C++ Abstract Class and Pure Virtual Function
// C++ program to calculate the area of a square and a circle
#include <iostream>
using namespace std;
// Abstract class
class Shape {
protected:
float dimension;
public:
void getDimension() {
cin >> dimension;
}
// pure virtual Function
virtual float calculateArea() = 0;
};
// Derived class
class Square : public Shape {
public:
float calculateArea() {
return dimension * dimension;
}
};
// Derived class
class Circle : public Shape {
public:
float calculateArea() {
return 3.14 * dimension * dimension;
}
};
int main() {
Square square;
Circle circle;
cout << "Enter the length of the square: ";
[Link]();
cout << "Area of square: " << [Link]() << endl;
cout << "\nEnter radius of the circle: ";
[Link]();
cout << "Area of circle: " << [Link]() << endl;
return 0;
}
Interfaces in C++
• All member functions are pure virtual
• Class cannot be instantiated
• Use public inheritance for implementation
• Include a virtual destructor to prevent memory leaks
Example: Payment Interface
#include <iostream>
using namespace std;
// Interface
class Payment {
public:
virtual void pay(int amount) = 0; // pure virtual function
virtual ~Payment() {} // virtual destructor
};
// Implementation 1
class CreditCard : public Payment {
public:
void pay(int amount) override {
cout << "Paid " << amount << " using Credit Card\n";
}
};
// Implementation 2
class UPI : public Payment {
public:
void pay(int amount) override {
cout << "Paid " << amount << " using UPI\n";
}
};
int main() {
Payment* p1 = new CreditCard();
Payment* p2 = new UPI();
p1->pay(1000);
p2->pay(500);
delete p1;
delete p2;
}
Memory Leaks in C++ & Virtual destructor
A memory leak occurs when a program allocates memory but never releases it, causing wasted
memory and possible program crashes over time.
1. Common Causes of Memory Leaks
1. Forgetting to delete allocated memory
2. Losing pointer reference
3. Missing virtual destructor
4. Exceptions thrown before delete
5. Circular references with shared_ptr
6. Incorrect copy constructors / assignment operator
Problem : Memory Leak Solution: Virtual Destructor
#include <iostream> #include <iostream>
using namespace std; using namespace std;
class Logger { class Logger {
public: public:
~Logger() { virtual ~Logger() {
cout << "Logger destructor\n"; cout << "Logger destructor\n";
} }
}; };
class FileLogger : public Logger { class FileLogger : public Logger {
FILE* file; FILE* file;
public: public:
FileLogger() { FileLogger() {
file = fopen("[Link]", "w"); file = fopen("[Link]", "w");
cout << "File opened\n"; cout << "File opened\n";
} }
~FileLogger() { ~FileLogger() {
fclose(file); fclose(file);
cout << "File closed\n"; cout << "File closed\n";
} }
}; };
int main() { int main() {
Logger* logger = new FileLogger(); Logger* logger = new FileLogger();
delete logger; // ❌ Problem delete logger; // ✅ Correct
} }
• delete obj uses runtime
• delete obj calls Base destructor only polymorphism
• Derived destructor is not called • Correct destructor is called using vtable
• Memory allocated in Derived is never • Derived resources are freed first
freed • Then Base cleanup happens
• ➝ Memory leak • ➝ No memory leak
Pure virtual functions
A pure virtual function is a virtual function that has no implementation in the base class
and must be overridden in the derived class.
It is declared using = 0.
Pure virtual functions are used to achieve abstraction by enforcing implementation in derived
classes.
A class that contains at least one pure virtual function is called an abstract class.
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() = 0; // pure virtual
virtual ~Shape() {} // virtual destructor
};
class Circle : public Shape {
public:
void draw() override {
cout << "Drawing Circle\n";
}
};
class Rectangle : public Shape {
public:
void draw() override {
cout << "Drawing Rectangle\n";
}
};
int main() {
Shape* s1 = new Circle();
Shape* s2 = new Rectangle();
s1->draw();
s2->draw();
delete s1;
delete s2;
}
O/P:-
Drawing Circle
Drawing Rectangle
NOTE:-
Abstraction Interfaces An interface in C++ is an abstract class with only pure virtual functions, used
to define a contract for derived classes.
POINTERS
C++ Standard Template Library (STL)
STL is a collection of pre-built classes and functions that make it easy to
manage data using common data structures like vectors, stacks, and
maps.
1. Vector
• Dynamic array, resizable
• Supports random access
• push_back() to add elements
• sort([Link](), [Link]()) to sort
2. Set
• Stores unique elements
• Automatically sorted
• No duplicates allowed
3. Map
• Stores key-value pairs
• Keys are unique
• Access value using m[key]
4. STL Algorithms
• Functions like sort(), count(), find(), etc.
• Work on containers with iterators
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm> // for sort
using namespace std;
int main() {
// 1. Vector (dynamic array)
vector<int> v = {5, 2, 8, 1};
v.push_back(10); // Add element at end
sort([Link](), [Link]()); // Sort vector
cout << "Vector elements: ";
for(int x : v)
cout << x << " ";
cout << endl;
// 2. Set (unique sorted elements)
set<int> s;
[Link](3);
[Link](1);
[Link](3); // duplicate ignored
cout << "Set elements: ";
for(int x : s)
cout << x << " ";
cout << endl;
// 3. Map (key-value pairs)
map<string, int> m;
m["Alice"] = 25;
m["Bob"] = 30;
cout << "Map elements:\n";
for(auto &p : m)
cout << [Link] << " => " << [Link] << endl;
// 4. Algorithm example (count)
int cnt = count([Link](), [Link](), 2);
cout << "Number of 2s in vector: " << cnt << endl;
return 0;
}
O/P
Vector elements: 1 2 5 8 10
Set elements: 1 3
Map elements:
Alice => 25
Bob => 30
Number of 2s in vector: 1
MISCELLANIOUS
1. Inline vs Macro
Feature Inline Macro
A function hint to the compiler to Preprocessor directive that replaces
Definition
replace function call with code code before compilation
inline int add(int a, int b) {
Syntax #define ADD(a,b) ((a)+(b))
return a+b; }
Type
Yes No type checking
checking
Scope Has scope No scope (textual replacement)
Debugging Easier Harder
Example
inline int square(int x) { return x*x; }
#define SQUARE(x) ((x)*(x))
Key Tip: Prefer inline functions over macros in C++.
2. Shallow Copy vs Deep Copy
Feature Shallow Copy Deep Copy
Copies only values, pointer variables point Copies values and dynamically
Definition
to the same memory allocated memory
Memory Shared memory for pointers Separate memory allocation
Problem Changes in one object affect the other No side effects
Example
class Demo {
int* ptr;
public:
Demo(int val) { ptr = new int(val); }
Demo(const Demo &obj) { ptr = new int(*[Link]); } // Deep copy
};
3. #define vs const
Feature #define const
Type checking None Yes
Scope Global Has scope
Memory No memory allocated Allocates memory
Example
#define PI 3.14
const double pi = 3.14;
4. auto Keyword
• Definition: Automatically deduces the type of variable at compile time.
• Example:
auto x = 10; // int
auto y = 3.14; // double
auto z = "Hello"; // const char*
5. Range-based for loop
• Definition: Iterates over elements of a container easily.
• Example:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1,2,3};
for(auto x : v)
cout << x << " ";
return 0;
}
6. Lambda Expressions
• Definition: Anonymous function used inline.
• Syntax: [capture](parameters){ body }
• Example:
auto sum = [](int a,int b){ return a+b; };
cout << sum(2,3); // 5
7. mutable Keyword
• Definition: Allows a member variable to be modified in a const object.
• Example:
class Demo {
mutable int counter;
public:
Demo() : counter(0) {}
void increment() const { counter++; }
};
8. explicit Keyword
• Definition: Prevents implicit type conversions for constructors.
• Example:
class Demo {
public:
explicit Demo(int x) {}
};
Demo d = 10; // Error without explicit
Demo d2(10); // OK
9. Difference between struct, union, and class
Feature struct union class
Default
public public private
access
Each member has Each member has
Memory All members share memory
separate memory separate memory
Feature struct union class
Save memory for mutually
Use Simple grouping OOP, encapsulation
exclusive data
Example
struct S { int x; int y; };
union U { int x; float y; };
class C { int x; public: void show(){}; };
10. How virtual table (vtable) works
• Definition: Supports runtime polymorphism in C++.
• Each class with virtual functions has a vtable pointer (vptr).
• At runtime, the correct function is called using vptr → vtable → function.
• Example:
class Base { virtual void show() {} };
class Derived : public Base { void show() override {} };
11. Null Pointer vs Dangling Pointer
Feature Null Pointer Dangling Pointer
Definition Pointer not pointing to any memory Pointer pointing to freed/deleted memory
Initialization int *p = nullptr; int *p = new int(5); delete p;
Safety Safe Dangerous, may cause undefined behavior
[Link] vs Array in C++
Feature Array Vector
Fixed-size collection of
Dynamic-size container from STL,
Definition elements stored in contiguous
resizable array
memory
Must be known at compile time
Size Can grow or shrink at runtime
(for static array)
Memory Static memory allocation Dynamic memory allocation
Access Random access using index Random access using [] or at()
Expensive (manual shifting Easy: push_back(), pop_back(),
Insertion/Deletion
required) insert(), erase()
Rich member functions (size(),
Functions No member functions empty(), begin(), end(), sort() via
algorithm)
Feature Array Vector
No bounds checking (arr[10]
Safety at() provides bounds checking
may cause undefined behavior)
Slightly faster (no extra Slightly slower due to dynamic
Performance
overhead) allocation
Initialization int arr[5] = {1,2,3,4,5}; vector<int> v = {1,2,3,4,5};
Standard Library Built-in STL container
Use Case When size is fixed When size may change dynamically
Example
Array
#include <iostream>
using namespace std;
int main() {
int arr[5] = {1, 2, 3, 4, 5};
arr[2] = 10; // update
cout << "Array element: " << arr[2] << endl;
return 0;
}
Vector
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1,2,3,4,5};
v.push_back(6); // add element
v[2] = 10; // update
cout << "Vector element: " << v[2] << endl;
cout << "Vector size: " << [Link]() << endl;
return 0;
}