0% found this document useful (0 votes)
1 views88 pages

C++ Notes

The document explains the concept of objects and classes in C++, emphasizing their role in Object-Oriented Programming (OOP). It covers the syntax for creating classes and objects, provides examples of how to group variables and methods, and discusses the evolution from structures in C to classes in C++. Key points include encapsulation, reusability, and the organization of code.

Uploaded by

lokeshdevathati
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views88 pages

C++ Notes

The document explains the concept of objects and classes in C++, emphasizing their role in Object-Oriented Programming (OOP). It covers the syntax for creating classes and objects, provides examples of how to group variables and methods, and discusses the evolution from structures in C to classes in C++. Key points include encapsulation, reusability, and the organization of code.

Uploaded by

lokeshdevathati
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Objects as a Group of Variables in C++

1. Introduction
In C++, objects are instances of a class.
A class is a user-defined data type that can group multiple variables (called data members)
and functions (called member functions) into a single unit.

So, an object acts as a collection of related variables (attributes) that describe a real-world
entity.

For example:

 A Student object may group variables like rollNo, name, marks.


 A Car object may group variables like brand, model, price.

This grouping is the foundation of Object-Oriented Programming (OOP).

2. Why Objects as Groups of Variables?


 Better organization: Instead of handling many independent variables, group them under
one object.
 Real-world modeling: Represents entities like "student", "book", "employee".
 Code reusability: Define once (class), use many times (objects).
 Encapsulation: Variables are protected inside objects and accessed in a controlled way.

3. Syntax
class ClassName {
public:
// variables (data members)
dataType var1;
dataType var2;
// ...
};

int main() {
ClassName obj; // creating an object
obj.var1 = value;
obj.var2 = value;
}

Here, obj groups together var1, var2, etc. as its own set of variables.

4. Example 1: Student as an Object


#include <iostream>
using namespace std;

class Student {
public:
int rollNo; // data members (variables)
string name;
float marks;
};

int main() {
Student s1; // object 1
[Link] = 101;
[Link] = "Loki";
[Link] = 92.5;

Student s2; // object 2


[Link] = 102;
[Link] = "Ravi";
[Link] = 88.0;

cout << "Student 1: " << [Link] << ", " << [Link] << ", " << [Link]
<< endl;
cout << "Student 2: " << [Link] << ", " << [Link] << ", " << [Link]
<< endl;

return 0;
}

Explanation:

 Student class groups variables: rollNo, name, marks.


 s1 and s2 are objects → each one maintains its own copy of these variables.
 Output shows that each object holds its own grouped data.

5. Example 2: Employee Object with Multiple Variables


#include <iostream>
using namespace std;

class Employee {
public:
int id;
string name;
double salary;
};

int main() {
Employee e1, e2;

// Assigning values to object e1


[Link] = 1;
[Link] = "Ananya";
[Link] = 50000;

// Assigning values to object e2


[Link] = 2;
[Link] = "Rahul";
[Link] = 60000;

// Displaying data
cout << "Employee 1 -> ID: " << [Link] << ", Name: " << [Link] << ",
Salary: " << [Link] << endl;
cout << "Employee 2 -> ID: " << [Link] << ", Name: " << [Link] << ",
Salary: " << [Link] << endl;

return 0;
}

Here, each object is a separate group of variables (like separate records in a database).

6. Example 3: Objects in Arrays (Multiple Groups)


#include <iostream>
using namespace std;

class Book {
public:
int bookID;
string title;
float price;
};

int main() {
Book books[3]; // array of objects

books[0].bookID = 1;
books[0].title = "C++ Basics";
books[0].price = 299.50;

books[1].bookID = 2;
books[1].title = "OOP Concepts";
books[1].price = 450.75;
books[2].bookID = 3;
books[2].title = "Data Structures";
books[2].price = 500.00;

// Displaying details
for (int i = 0; i < 3; i++) {
cout << "Book " << i+1 << ": "
<< books[i].bookID << ", "
<< books[i].title << ", "
<< books[i].price << endl;
}

return 0;
}

An array of objects groups many sets of variables into a single structure (like a library database
of books).

7. Key Points to Remember


 A class defines the blueprint (what variables the object will have).
 An object is a collection of variables (data members) that belong together.
 Each object has its own copy of the class variables.
 Objects can be stored individually or in arrays.
 This concept is the basis for real-world modeling in OOP.
Classes as a Named Group of Methods and
Data in C++
1. Introduction
In C++, a class is a user-defined data type that acts as a blueprint for creating objects.

A class groups together:

 Data members (variables) → store the state (attributes) of the object.


 Member functions (methods) → define behavior (actions) of the object.

Thus, a class is a named group that combines variables and functions into a single unit.

2. Why Use Classes?


 Encapsulation: Data + Methods are bundled together.
 Reusability: One class definition can create multiple objects.
 Abstraction: Expose only what’s necessary through methods.
 Organization: Code becomes modular and structured.
 Real-world modeling: Example → Car class groups brand, model, speed (data) and
accelerate(), brake() (methods).

3. Syntax of a Class
class ClassName {
public:
// data members
dataType variable1;
dataType variable2;

// member functions (methods)


void method1() {
// code
}
returnType method2(parameters) {
// code
}
};
Important Points:

 Keyword class defines a class.


 Access specifiers: public, private, protected control visibility.
 Objects are created using the class name.

4. Example 1: Student Class with Data and Methods


#include <iostream>
using namespace std;

class Student {
public:
// data members
int rollNo;
string name;
float marks;

// member function
void displayDetails() {
cout << "Roll No: " << rollNo
<< ", Name: " << name
<< ", Marks: " << marks << endl;
}
};

int main() {
Student s1; // create object

[Link] = 101;
[Link] = "Loki";
[Link] = 95.5;

[Link](); // calling method

return 0;
}

Explanation:

 Data members: rollNo, name, marks.


 Member function: displayDetails() → prints details.
 s1 is an object → holds its own data + can use methods.
5. Example 2: Car Class (Real-world Modeling)
#include <iostream>
using namespace std;

class Car {
public:
string brand;
int speed;

void accelerate() {
speed += 10;
cout << brand << " accelerated. Speed = " << speed << endl;
}

void brake() {
speed -= 10;
cout << brand << " slowed down. Speed = " << speed << endl;
}
};

int main() {
Car c1;
[Link] = "Tesla";
[Link] = 50;

[Link](); // method modifies data


[Link]();

return 0;
}

Here, data members (brand, speed) represent the state of the car,
and methods (accelerate(), brake()) define its behavior.

6. Example 3: Employee Class with Constructor


#include <iostream>
using namespace std;

class Employee {
public:
int id;
string name;
double salary;

// constructor (method called when object is created)


Employee(int empId, string empName, double empSalary) {
id = empId;
name = empName;
salary = empSalary;
}

void showInfo() {
cout << "ID: " << id
<< ", Name: " << name
<< ", Salary: " << salary << endl;
}
};

int main() {
Employee e1(1, "Ananya", 50000);
Employee e2(2, "Rahul", 60000);

[Link]();
[Link]();

return 0;
}

Constructors are special methods used to initialize data when objects are created.

7. Objects as Instances of a Class


 A class is only a definition (like a blueprint).
 Objects are the real instances created from that class.
 Each object maintains its own copy of the data members.
 All objects share the methods defined in the class.

8. Key Points to Remember


 A class = named group of data + methods.
 Encapsulation = bundling variables and functions.
 Objects are instances of classes.
 Access specifiers:
o public: accessible from outside.
o private: accessible only inside class.
o protected: accessible in inheritance.
 Methods can access and modify data members.
Morphing from Structure to Classes in C++
1. Background
 In C language, struct is used to group variables of different data types under one name.
 But C structures only hold data; they cannot have functions (methods) inside them.
 C++ enhances structures and introduces classes, which can group both data and
functions.
 This evolution is called morphing from structures to classes.

2. Structure in C (Data Only)


#include <stdio.h>
#include <string.h>

struct Student {
int rollNo;
char name[20];
float marks;
};

int main() {
struct Student s1;
[Link] = 101;
strcpy([Link], "Loki");
[Link] = 92.5;

printf("Roll: %d, Name: %s, Marks: %.2f", [Link], [Link], [Link]);


return 0;
}

Here, Student groups data but cannot have functions like display() inside.

3. Structure in C++ (Data + Functions Allowed)


C++ extends struct → it can have methods just like classes (default access is public).

#include <iostream>
using namespace std;

struct Student {
int rollNo;
string name;
float marks;
// method inside structure
void display() {
cout << "Roll: " << rollNo << ", Name: " << name
<< ", Marks: " << marks << endl;
}
};

int main() {
Student s1 = {101, "Loki", 92.5};
[Link]();
return 0;
}

Notice: In C++, structures can also hold methods, making them closer to classes.

4. Classes in C++ (Full OOP)


Classes generalize and extend structures:

 Support data + methods.


 Support access specifiers: public, private, protected.
 Support constructors, destructors, inheritance, polymorphism, abstraction,
encapsulation.

#include <iostream>
using namespace std;

class Student {
private:
int rollNo;
string name;
float marks;

public:
// constructor
Student(int r, string n, float m) {
rollNo = r;
name = n;
marks = m;
}

void display() {
cout << "Roll: " << rollNo
<< ", Name: " << name
<< ", Marks: " << marks << endl;
}
};

int main() {
Student s1(101, "Loki", 92.5);
[Link]();
return 0;
}

Classes take the idea of grouping data (like structs) and extend it with OOP features.

5. Key Differences Between struct and class in C++


Feature struct (in C++) class (in C++)
Default Access public private
Data Members Allowed Allowed
Member Functions Allowed Allowed
Constructors/Destructors Allowed Allowed
Allowed (public by
Inheritance Allowed (private by default)
default)
Full (Encapsulation, Inheritance,
OOP Features Limited
Polymorphism)

6. Morphing Pathway (Evolution)


1. C struct → only data grouping.
2. C++ struct → data + functions (like lightweight classes).
3. C++ class → advanced form → full OOP support.

Thus, class = evolved struct with access control + OOP features.

7. Example: Morphing Step-by-Step


Step 1: C Style Struct (Data Only)
struct Employee {
int id;
char name[20];
float salary;
};

Step 2: C++ Struct (Data + Methods)


struct Employee {
int id;
string name;
float salary;

void display() {
cout << id << " " << name << " " << salary << endl;
}
};

Step 3: C++ Class (Encapsulation + OOP)


class Employee {
private:
int id;
string name;
float salary;

public:
Employee(int i, string n, float s) {
id = i;
name = n;
salary = s;
}

void display() {
cout << id << " " << name << " " << salary << endl;
}
};

Summary:

 In C, struct = group of variables.


 In C++, struct = group of variables + methods (default public).
 In C++, class = full OOP unit (variables + methods + encapsulation + inheritance +
polymorphism).
 Thus, classes are the natural evolution (morphing) of structures in C++.
Input and Output in C++
1. Introduction
 Input/Output (I/O) in C++ is handled using the iostream library.
 It provides stream objects for reading input and writing output.
 Streams = sequences of bytes that represent data flow.
o Input stream → data flows from keyboard to program.
o Output stream → data flows from program to screen.

2. Standard I/O Objects


C++ defines three main I/O objects in <iostream>:

Object Type Purpose


cin istream Standard input (keyboard)
cout ostream Standard output (monitor)
cerr ostream Standard error (unbuffered)
clog ostream Standard error (buffered log)

3. Output in C++ → cout


 cout is used to display output on the screen.
 Operator used: insertion operator <<.

Example 1: Basic Output


#include <iostream>
using namespace std;

int main() {
cout << "Hello, World!" << endl;
cout << "C++ Output Example" << endl;
return 0;
}

endl → inserts a newline (like \n) and flushes the buffer.


4. Input in C++ → cin
 cinis used to take input from the user (keyboard).
 Operator used: extraction operator >>.

Example 2: Basic Input


#include <iostream>
using namespace std;

int main() {
int age;
cout << "Enter your age: ";
cin >> age; // input from user
cout << "You entered age = " << age << endl;
return 0;
}

cin automatically skips whitespace (spaces, tabs, newlines) when reading numbers or single
words.

5. Multiple Inputs and Outputs


Example 3: Taking Multiple Values
#include <iostream>
using namespace std;

int main() {
int a, b;
cout << "Enter two numbers: ";
cin >> a >> b; // input two integers
cout << "Sum = " << a + b << endl;
return 0;
}

6. Strings with cin and getline()


 cin stops reading at space/tab/newline.
 To read full lines (with spaces) → use getline().

Example 4: Difference Between cin and getline()


#include <iostream>
using namespace std;
int main() {
string name;

cout << "Enter your first name: ";


cin >> name; // stops at space
cout << "Hello, " << name << endl;

[Link](); // clear leftover newline in buffer

cout << "Enter your full name: ";


getline(cin, name); // reads full line with spaces
cout << "Welcome, " << name << endl;

return 0;
}

7. Formatted Output (iomanip)


Header <iomanip> provides manipulators for formatting output.

Example 5: Using setw, setprecision


#include <iostream>
#include <iomanip>
using namespace std;

int main() {
double pi = 3.1415926535;

cout << "Default: " << pi << endl;


cout << "Fixed (2 decimals): " << fixed << setprecision(2) << pi << endl;
cout << "Scientific: " << scientific << pi << endl;

return 0;
}

Common manipulators:

 setw(n) → set field width.


 setprecision(n) → number of decimal places.
 fixed → fixed-point notation.
 scientific → scientific notation.

8. Error Output → cerr vs clog


 cerr → displays error messages (unbuffered).
 clog → used for logging messages (buffered).

Example 6:
#include <iostream>
using namespace std;

int main() {
cerr << "This is an error message!" << endl;
clog << "This is a log message!" << endl;
return 0;
}

9. Summary
 cin → input using >>.
 cout → output using <<.
 cerr → immediate error messages.
 clog → buffered error/log messages.
 getline() → reads full string including spaces.
 <iomanip> → formatting output.
Access Specifiers in C++
1. Introduction
In C++, access specifiers are keywords used to define the visibility (scope) of data members
(variables) and member functions (methods) inside a class.

They implement Encapsulation → one of the pillars of Object-Oriented Programming


(OOP).

They control who can access what in your class.

2. Types of Access Specifiers


There are three main access specifiers in C++:

Specifier Accessibility Meaning


Accessible from anywhere (inside & outside the Represents an external
public
class). interface of the class.
Accessible only inside the class. Not accessible Used to hide data (data
private
from outside. hiding).
Accessible inside the class and in derived
protected Used in inheritance.
(inherited) classes, but not outside.

3. Syntax
class ClassName {
private:
// private members
public:
// public members
protected:
// protected members
};

By default:

 In class, members are private if no specifier is mentioned.


 In struct, members are public if no specifier is mentioned.
4. Example 1: Public Members
#include <iostream>
using namespace std;

class Student {
public:
int rollNo; // public data
string name;

void display() { // public method


cout << "Roll: " << rollNo << ", Name: " << name << endl;
}
};

int main() {
Student s1;
[Link] = 101; // direct access (allowed)
[Link] = "Loki";
[Link](); // allowed
return 0;
}

Public members are accessible directly from outside the class.

5. Example 2: Private Members


#include <iostream>
using namespace std;

class BankAccount {
private:
int accountNumber; // private data
double balance;

public:
void setAccount(int acc, double bal) {
accountNumber = acc;
balance = bal;
}
void showAccount() {
cout << "Account: " << accountNumber << ", Balance: " << balance <<
endl;
}
};

int main() {
BankAccount acc1;
// [Link] = 123; ❌ Error: private member
[Link](123, 5000); // Access through method
[Link]();
return 0;
}

Private members cannot be accessed directly → must use public methods (getter/setter).
This enforces data hiding.

6. Example 3: Protected Members (Inheritance)


#include <iostream>
using namespace std;

class Person {
protected:
string name; // protected member
public:
void setName(string n) {
name = n;
}
};

class Student : public Person { // derived class


public:
void display() {
cout << "Student Name: " << name << endl; // accessible (protected →
child class)
}
};

int main() {
Student s1;
[Link]("Loki");
[Link]();
// cout << [Link]; ❌ Error: protected (not accessible outside)
return 0;
}

Protected members are not public, but they are accessible in derived classes.
7. Access Specifiers in Inheritance
When a class is inherited, the access specifiers affect how base class members are accessible in
the derived class.

Inheritance Public Members of Protected Members of Private Members of


Type Base Base Base
Public Public in Derived Protected in Derived Not Inherited
Protected Protected in Derived Protected in Derived Not Inherited
Private Private in Derived Private in Derived Not Inherited

8. Real-Life Analogy
Think of a Company Employee Record:

 public: Employee ID card (anyone can see).


 private: Salary details (hidden, only HR can see).
 protected: Internal company data (accessible by management, not outsiders).

9. Quick Diagram
+---------------------+
| Class |
+---------------------+
Public | visible everywhere |
Private| visible only inside |
Protected | visible in class & children |
+---------------------+

10. Summary
 public → Accessible everywhere.
 private → Accessible only inside class.
 protected → Accessible in class & subclasses.
 Default:
o Class → private.
o Struct → public.
Member Functions in C++
1. Introduction
 In C++, a member function is a function that is defined inside a class and operates on
the class’s data members.
 Member functions represent the behavior (actions) of objects.
 They are tightly bound to the class and can access private, protected, and public data
members.

Think of a class as a blueprint:

 Data members = variables (attributes).


 Member functions = methods (behaviors).

2. Syntax
Inside the Class (Inline Definition)
class ClassName {
public:
void functionName() {
// code
}
};

Outside the Class (Using Scope Resolution ::)


class ClassName {
public:
void functionName(); // declaration only
};

// definition outside the class


void ClassName::functionName() {
// code
}

3. Example 1: Defining Member Function Inside the Class


#include <iostream>
using namespace std;

class Student {
public:
int rollNo;
string name;

void display() { // member function defined inside


cout << "Roll: " << rollNo << ", Name: " << name << endl;
}
};

int main() {
Student s1;
[Link] = 101;
[Link] = "Loki";
[Link](); // calling member function
return 0;
}

Functions defined inside the class are inline by default.

4. Example 2: Defining Member Function Outside the Class


#include <iostream>
using namespace std;

class Student {
public:
int rollNo;
string name;

void display(); // declaration


};

// definition outside
void Student::display() {
cout << "Roll: " << rollNo << ", Name: " << name << endl;
}

int main() {
Student s1;
[Link] = 102;
[Link] = "Ravi";
[Link]();
return 0;
}

Using scope resolution operator :: tells the compiler that the function belongs to the class.
5. Types of Member Functions
(a) Simple Member Functions

Perform basic operations.


Example: display(), setData().

(b) Inline Member Functions

Functions defined inside class are treated as inline (compiler may replace the function call with
function body).
Reduces function call overhead for small functions.

(c) Accessor Functions (Getters)

Return values of private data members.

class Employee {
private:
int salary;
public:
void setSalary(int s) { salary = s; }
int getSalary() { return salary; } // accessor
};

(d) Mutator Functions (Setters)

Modify private data members.


(Above setSalary() is a mutator).

(e) Static Member Functions

Belong to the class rather than any specific object.


Declared with keyword static.

class Counter {
private:
static int count;
public:
Counter() { count++; }
static int getCount() { return count; }
};
int Counter::count = 0;
(f) Const Member Functions

Cannot modify class data.

class Student {
private:
string name;
public:
Student(string n) : name(n) {}
void display() const { // const function
cout << "Name: " << name << endl;
}
};

6. Example 3: Using Getters & Setters


#include <iostream>
using namespace std;

class BankAccount {
private:
int accountNo;
double balance;

public:
void setAccount(int acc, double bal) {
accountNo = acc;
balance = bal;
}

void deposit(double amt) {


balance += amt;
}

double getBalance() { // accessor


return balance;
}
};

int main() {
BankAccount b1;
[Link](123, 1000);
[Link](500);
cout << "Balance: " << [Link]() << endl;
return 0;
}
7. Key Points
 Member functions define behavior of objects.
 Can be defined inside or outside the class.
 Access private/protected data directly.
 Types include: inline, static, const, getter, setter.
 Accessed using dot operator (.) with object.

8. Real-Life Analogy
Think of a Car class:

 Data members → speed, fuel.


 Member functions → accelerate(), brake(), refuel().

Functions describe how the car behaves.

Summary

 Member functions = class methods.


 Defined inside (inline) or outside (using ::).
 Used for encapsulation and managing data members.
 Types: normal, inline, static, const, getters, setters.
Accessor, Mutator, and Auxiliary Functions
in C++
1. Introduction
In Object-Oriented Programming (OOP), we often keep data members private to implement
data hiding (Encapsulation).
To work with these private variables, we use special types of member functions:

1. Accessors (Getters) → Read values.


2. Mutators (Setters) → Modify values.
3. Auxiliary Functions → Perform extra/supporting tasks (not just get/set).

2. Accessor Functions (Getters)


 Purpose: Return (access) the value of private data members.
 Do not modify the data members.
 Usually declared as const functions (to ensure no modification).

Example
#include <iostream>
using namespace std;

class Student {
private:
int rollNo;
float marks;

public:
Student(int r, float m) {
rollNo = r;
marks = m;
}

// Accessor functions
int getRollNo() const { return rollNo; }
float getMarks() const { return marks; }
};

int main() {
Student s1(101, 95.5);
cout << "Roll: " << [Link]() << ", Marks: " << [Link]() <<
endl;
return 0;
}
Here getRollNo() and getMarks() are accessors.

3. Mutator Functions (Setters)


 Purpose: Change (mutate) the value of private data members.
 Provide controlled modification of data.
 Can include validation logic before updating.

Example
#include <iostream>
using namespace std;

class BankAccount {
private:
int accountNo;
double balance;

public:
void setAccount(int acc) { accountNo = acc; }

void setBalance(double bal) {


if (bal >= 0) // validation
balance = bal;
else
cout << "Invalid balance!" << endl;
}

double getBalance() const { return balance; } // accessor


};

int main() {
BankAccount b1;
[Link](123);
[Link](5000); // mutator
cout << "Balance = " << [Link]() << endl;
return 0;
}

setBalance() is a mutator because it modifies private data.

4. Auxiliary Functions
 Purpose: Perform additional operations using the class data, but not strictly just get/set.
 They often process, calculate, or display data.
 Sometimes called helper functions.
Example
#include <iostream>
using namespace std;

class Rectangle {
private:
int length, width;

public:
Rectangle(int l, int w) {
length = l;
width = w;
}

// Accessor
int getLength() const { return length; }

// Mutator
void setWidth(int w) { width = w; }

// Auxiliary function
int area() const { return length * width; }
void display() const {
cout << "Length = " << length << ", Width = " << width
<< ", Area = " << area() << endl;
}
};

int main() {
Rectangle r1(10, 5);
[Link](); // auxiliary
[Link](8); // mutator
cout << "New Area = " << [Link]() << endl; // auxiliary
return 0;
}

area() and display() are auxiliary functions because they process/represent data rather
than just read/write it.

5. Summary Table
Function
Purpose Example
Type
Accessor Read/return private data (no modification). getMarks()
Mutator Modify/update private data (with validation). setBalance()
Perform additional tasks like compute, display, or process area(),
Auxiliary
data. display()
6. Real-Life Analogy
Consider a Bank ATM Machine:

 Accessor → Check balance (read-only).


 Mutator → Deposit or withdraw money (update balance).
 Auxiliary → Print receipt, calculate interest, show transaction history.

Final Takeaway

 Accessor (Getter) → Only reads data.


 Mutator (Setter) → Only writes/updates data.
 Auxiliary → Performs extra tasks like calculations, processing, or display.
Constructors and Destructors in C++
1. Introduction
In C++, objects are created from classes.

 When an object is created, we may need to initialize data members.


 When an object is destroyed, we may need to release resources.

This is handled by constructors and destructors.

2. Constructor
Definition

 A constructor is a special member function that is automatically called when an


object is created.
 Its main purpose is to initialize the object’s data members.

Rules

 Name of constructor = same as class name.


 No return type (not even void).
 Can be overloaded (multiple constructors).
 Can take parameters (Parameterized Constructor).
 Can provide defaults (Default Constructor).

Example 1: Default Constructor


#include <iostream>
using namespace std;

class Student {
private:
int rollNo;
string name;

public:
// Default constructor
Student() {
rollNo = 0;
name = "Unknown";
cout << "Default Constructor called" << endl;
}

void display() {
cout << "Roll: " << rollNo << ", Name: " << name << endl;
}
};

int main() {
Student s1; // constructor called automatically
[Link]();
return 0;
}

Constructor automatically initializes values.

Example 2: Parameterized Constructor


#include <iostream>
using namespace std;

class Student {
private:
int rollNo;
string name;

public:
// Parameterized constructor
Student(int r, string n) {
rollNo = r;
name = n;
cout << "Parameterized Constructor called" << endl;
}

void display() {
cout << "Roll: " << rollNo << ", Name: " << name << endl;
}
};

int main() {
Student s1(101, "Loki"); // constructor with arguments
Student s2(102, "Ravi");
[Link]();
[Link]();
return 0;
}

Example 3: Constructor Overloading


#include <iostream>
using namespace std;
class Rectangle {
private:
int length, width;

public:
Rectangle() { // default
length = 0; width = 0;
}

Rectangle(int l, int w) { // parameterized


length = l; width = w;
}

Rectangle(int s) { // square case


length = width = s;
}

void display() {
cout << "Length = " << length << ", Width = " << width << endl;
}
};

int main() {
Rectangle r1; // default
Rectangle r2(10,5); // parameterized
Rectangle r3(7); // overloaded
[Link]();
[Link]();
[Link]();
return 0;
}

3. Destructor
Definition

 A destructor is a special member function that is automatically called when an object


is destroyed (goes out of scope or program ends).
 Its main purpose is to release resources (memory, file handles, database connections,
etc.).

Rules

 Name of destructor = ~ followed by class name.


 No return type and no arguments.
 Only one destructor per class (cannot be overloaded).
 Called automatically in reverse order of object creation.
Example: Destructor
#include <iostream>
using namespace std;

class Student {
private:
int rollNo;
public:
Student(int r) {
rollNo = r;
cout << "Constructor called for Roll " << rollNo << endl;
}

~Student() { // destructor
cout << "Destructor called for Roll " << rollNo << endl;
}
};

int main() {
Student s1(101);
Student s2(102);
cout << "Inside main function" << endl;
return 0;
} // destructors called automatically here

Output Order:

Constructor called for Roll 101


Constructor called for Roll 102
Inside main function
Destructor called for Roll 102
Destructor called for Roll 101

Destructors are called in reverse order of creation.

4. Key Differences
Feature Constructor Destructor
Purpose Initialize object Destroy object / free resources
Name Same as class ~ClassName
Return type None None
Arguments Allowed (overloading possible) Not allowed
Count per class Multiple (overloading) Only one
Called when Object is created Object goes out of scope
5. Real-Life Analogy
 Constructor → Opening a file. (setup stage)
 Destructor → Closing the file. (cleanup stage)

6. Special Types
 Copy Constructor → Creates a new object as a copy of another object.
 Dynamic Memory Cleanup → Destructor is used with new/delete for memory
management.

Final Takeaway

 Constructor → Automatically called on object creation.


 Destructor → Automatically called on object destruction.
 Constructors can be default, parameterized, overloaded.
 Destructor is unique and cannot be overloaded.
new and delete Operators in C++
1. Introduction
 In C, memory is allocated dynamically using malloc() and freed using free().
 In C++, we use new and delete operators for dynamic memory management.
 They are more powerful and safer than malloc/free because they also call
constructors/destructors automatically.

2. new Operator
 Purpose: Allocates memory at runtime (on heap) for variables or objects.
 Returns a pointer to the allocated memory.
 Syntax:

pointer = new datatype; // single variable


pointer = new datatype[size]; // array of variables

Example 1: Allocating Single Variable


#include <iostream>
using namespace std;

int main() {
int *p = new int; // allocate memory for one integer
*p = 50; // assign value
cout << "Value: " << *p << endl;
delete p; // free memory
return 0;
}

new int allocates memory for one integer on heap.


delete p frees that memory.

Example 2: Allocating Array


#include <iostream>
using namespace std;

int main() {
int *arr = new int[5]; // allocate array of 5 integers
// store values
for (int i = 0; i < 5; i++) {
arr[i] = (i + 1) * 10;
}

// display values
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
cout << endl;

delete[] arr; // free entire array


return 0;
}

For arrays, we use delete[] instead of delete.

3. delete Operator
 Purpose: Deallocates memory that was allocated with new.
 Prevents memory leaks (unused memory that is never freed).
 Syntax:

delete pointer; // for single variable


delete[] pointer; // for array

4. new and delete with Objects


Example 3: Creating Single Object
#include <iostream>
using namespace std;

class Student {
public:
Student() { cout << "Constructor called" << endl; }
~Student() { cout << "Destructor called" << endl; }
void display() { cout << "Hello Student!" << endl; }
};

int main() {
Student *s = new Student; // constructor called
s->display();
delete s; // destructor called
return 0;
}
Example 4: Creating Array of Objects
#include <iostream>
using namespace std;

class Student {
public:
Student() { cout << "Constructor called" << endl; }
~Student() { cout << "Destructor called" << endl; }
};

int main() {
Student *arr = new Student[3]; // 3 objects created
delete[] arr; // destructors called for all
return 0;
}

new automatically calls the constructor.


delete automatically calls the destructor.

5. Difference: new/delete vs malloc/free


Feature new/delete malloc/free
Language C++ C
Correct type (no cast
Return Type void* (needs cast)
needed)
Yes (calls
Constructor/Destructor No
automatically)
Student *s = new Student *s =
Syntax Student; (Student*)malloc(sizeof(Student));
Throws bad_alloc
Exception Handling Returns NULL on failure
on failure

6. Real-Life Analogy
 new → Like booking a hotel room (you get space + setup).
 delete → Like checking out of the room (releasing space).

7. Key Points
 Always pair new with delete and new[] with delete[].
 Failing to use delete causes memory leaks.
 Using delete on already deleted memory = undefined behavior.

Final Takeaway

 Use new for dynamic allocation, delete to free memory.


 Use new[] and delete[] for arrays.
 Constructors & destructors are automatically called with new/delete.
 Safer and more OOP-friendly than malloc/free.
Overloading in C++
1. Introduction
In C++, overloading means using the same name for more than one function or operator, but
with different meanings depending on context.

It improves readability and allows polymorphism (same function/operator behaves differently


depending on inputs).

There are two main types:

1. Function Overloading
2. Operator Overloading

2. Function Overloading
Definition

Function overloading means multiple functions with the same name but different parameter
lists (number or type).

The compiler decides which function to call based on arguments (compile-time


polymorphism).

Rules

 Same function name.


 Different number or types of parameters.
 Return type alone cannot distinguish overloaded functions.

Example 1: Function Overloading (Different Parameters)


#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 << "Sum (int): " << [Link](10, 20) << endl;
cout << "Sum (double): " << [Link](2.5, 3.7) << endl;
cout << "Sum (3 int): " << [Link](5, 10, 15) << endl;
return 0;
}

Same function name add, but behaves differently based on arguments.

3. Operator Overloading
Definition

C++ allows us to redefine operators (like +, -, ==) for user-defined types (classes/objects).
This is called operator overloading.

Rules

 At least one operand must be a user-defined type.


 Certain operators (like . .* :: sizeof ?:) cannot be overloaded.
 Implemented using keyword operator.

Example 2: Operator Overloading (+ for Complex Numbers)


#include <iostream>
using namespace std;

class Complex {
private:
int real, imag;

public:
Complex(int r = 0, int i = 0) {
real = r;
imag = i;
}
// Operator overloading
Complex operator+(const Complex& c) {
return Complex(real + [Link], imag + [Link]);
}

void display() {
cout << real << " + " << imag << "i" << endl;
}
};

int main() {
Complex c1(3, 4), c2(1, 2);
Complex c3 = c1 + c2; // uses overloaded operator
[Link]();
return 0;
}

Here, the + operator is overloaded to add two complex numbers.

Example 3: Overloading ==
#include <iostream>
using namespace std;

class Student {
private:
int rollNo;
public:
Student(int r) : rollNo(r) {}

// Overload ==
bool operator==(const Student& s) {
return rollNo == [Link];
}
};

int main() {
Student s1(101), s2(101), s3(102);

if (s1 == s2)
cout << "s1 and s2 are equal" << endl;
else
cout << "s1 and s2 are not equal" << endl;

if (s1 == s3)
cout << "s1 and s3 are equal" << endl;
else
cout << "s1 and s3 are not equal" << endl;

return 0;
}
4. Difference: Function vs Operator Overloading
Feature Function Overloading Operator Overloading
Same function name, different Redefining operators for user-
Definition
parameters defined types
Purpose Convenience, readability Extend operators for objects
add(int, int) and add(double,
Example double)
Overloading + for Complex class
Compile-time
Yes (resolved by arguments) Yes (resolved by operands)
decision

5. Real-Life Analogy
 Function Overloading → Like the word "run" (you can run a race, run a machine, run a
program → same word, different meaning).
 Operator Overloading → Like + sign (adds numbers, concatenates strings, merges lists
→ same symbol, different actions).

6. Key Points
 Overloading provides compile-time polymorphism.
 Function Overloading → Same function, different arguments.
 Operator Overloading → Redefining operators for classes.
 Cannot overload ::, . , .*, sizeof, ?:.

Final Takeaway

 Overloading = Same name, different behavior (based on input type/number).


 Helps achieve polymorphism in C++.
 Includes Function Overloading and Operator Overloading.
Inheritance in C++
1. Introduction
 Inheritance is an Object-Oriented Programming (OOP) feature that allows a class to
reuse properties and behaviors of another class.
 The class that inherits is called the Derived (Child) Class.
 The class that is inherited from is called the Base (Parent) Class.

Main purpose → Reusability & Polymorphism.

2. Syntax
class Base {
// data members & member functions
};

class Derived : access_specifier Base {


// extra members & functions
};

 access_specifier → public, protected, or private (controls how base members are


inherited).

3. Example 1: Simple Inheritance


#include <iostream>
using namespace std;

class Person { // Base class


public:
string name;
int age;

void showDetails() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};

class Student : public Person { // Derived class


public:
int rollNo;

void showStudent() {
cout << "Roll No: " << rollNo << endl;
}
};

int main() {
Student s1;
[Link] = "Loki"; // inherited
[Link] = 21; // inherited
[Link] = 101; // own member

[Link](); // base class function


[Link](); // derived class function
return 0;
}

Student automatically gets access to name, age, and showDetails() from Person.

4. Types of Inheritance in C++


(a) Single Inheritance

One base class → one derived class.

class A { };
class B : public A { };

(b) Multilevel Inheritance

A derived class is further used as a base class.

class A { };
class B : public A { };
class C : public B { };

(c) Multiple Inheritance

Derived class inherits from more than one base class.

class A { };
class B { };
class C : public A, public B { };

(d) Hierarchical Inheritance

One base class → multiple derived classes.

class A { };
class B : public A { };
class C : public A { };

(e) Hybrid Inheritance

Combination of more than one type (e.g., multiple + multilevel).

5. Access Specifiers in Inheritance


Base Member Public Inheritance Protected Inheritance Private Inheritance
Public Public in derived Protected in derived Private in derived
Protected Protected in derived Protected in derived Private in derived
Private Not inherited Not inherited Not inherited

Default inheritance type:

 class → private
 struct → public

6. Example 2: Multilevel Inheritance


#include <iostream>
using namespace std;

class LivingBeing {
public:
void breathe() {
cout << "Breathing..." << endl;
}
};

class Person : public LivingBeing {


public:
void speak() {
cout << "Speaking..." << endl;
}
};

class Student : public Person {


public:
void study() {
cout << "Studying..." << endl;
}
};

int main() {
Student s;
[Link](); // from LivingBeing
[Link](); // from Person
[Link](); // own
return 0;
}

7. Example 3: Multiple Inheritance


#include <iostream>
using namespace std;

class Teacher {
public:
void teach() {
cout << "Teaching..." << endl;
}
};

class Researcher {
public:
void research() {
cout << "Researching..." << endl;
}
};

class Professor : public Teacher, public Researcher {


public:
void guideStudents() {
cout << "Guiding students..." << endl;
}
};

int main() {
Professor p;
[Link](); // from Teacher
[Link](); // from Researcher
[Link]();// own
return 0;
}

Here, Professor inherits from both Teacher and Researcher.

8. Constructor & Destructor in Inheritance


 Base class constructor is called first.
 Derived class constructor is called after base constructor.
 Destructor order is reverse (Derived → Base).
Example
#include <iostream>
using namespace std;

class Base {
public:
Base() { cout << "Base Constructor\n"; }
~Base() { cout << "Base Destructor\n"; }
};

class Derived : public Base {


public:
Derived() { cout << "Derived Constructor\n"; }
~Derived() { cout << "Derived Destructor\n"; }
};

int main() {
Derived d;
return 0;
}

Output:

Base Constructor
Derived Constructor
Derived Destructor
Base Destructor

9. Advantages of Inheritance
Code reusability (don’t rewrite).
Easier maintenance.
Supports polymorphism.
Models real-world relationships.

10. Real-Life Analogy


Think of Inheritance like a family tree:

 Parent has features (eyes, height).


 Child inherits them, plus can add new features.
 Grandchild inherits from child and so on.
Final Takeaway

 Inheritance allows reusing base class features in derived classes.


 Types: Single, Multilevel, Multiple, Hierarchical, Hybrid.
 Access specifiers control visibility in derived class.
 Constructors run Base → Derived, destructors run Derived → Base.
Handling Access and Specialization through
Overriding in C++
1. Introduction
When we use inheritance, the derived class often needs to:

1. Access base class features (maybe with modified visibility).


2. Specialize or modify base class behavior for its own needs.

This is achieved by overriding (redefining base class functions in derived classes).

2. Function Overriding
 Definition: Function overriding occurs when a derived class has a function with the
same name, return type, and parameters as in the base class.
 Used to provide a specialized implementation.
 Achieved using inheritance + virtual functions.

3. Syntax
class Base {
public:
virtual void show() { // base version
cout << "Base class function" << endl;
}
};

class Derived : public Base {


public:
void show() override { // overrides base version
cout << "Derived class function" << endl;
}
};

4. Example 1: Specialization through Overriding


#include <iostream>
using namespace std;
class Animal {
public:
virtual void sound() { // base class general behavior
cout << "Some generic animal sound" << endl;
}
};

class Dog : public Animal {


public:
void sound() override { // specialized behavior
cout << "Bark!" << endl;
}
};

class Cat : public Animal {


public:
void sound() override {
cout << "Meow!" << endl;
}
};

int main() {
Animal *a; // base class pointer

a = new Dog(); // dynamic polymorphism


a->sound(); // Bark!

a = new Cat();
a->sound(); // Meow!

delete a;
return 0;
}

Here:

 Base provides general definition.


 Derived classes override to specialize behavior.

5. Handling Access in Overriding


 The access specifier (public, protected, private) in the derived class controls how
overridden methods are accessed.
 Base class method might be public, but in derived class you can restrict access.

Example 2: Access Control


#include <iostream>
using namespace std;
class Base {
public:
virtual void display() {
cout << "Base Display" << endl;
}
};

class Derived : public Base {


private: // more restrictive
void display() override {
cout << "Derived Display" << endl;
}
};

int main() {
Base *b = new Derived();
b->display(); // still works because called through Base pointer
delete b;
return 0;
}

Even if Derived::display is private, it still overrides Base::display.


But direct object calls on Derived won’t work ([Link]() gives error).

6. Example 3: Specialization with Extended Behavior


Derived classes can also extend functionality while still using base behavior via
Base::function() call.

#include <iostream>
using namespace std;

class Shape {
public:
virtual void draw() {
cout << "Drawing a generic shape" << endl;
}
};

class Circle : public Shape {


public:
void draw() override {
cout << "Drawing a circle" << endl;
Shape::draw(); // also call base class version
}
};

int main() {
Circle c;
[Link]();
return 0;
}

Output:

Drawing a circle
Drawing a generic shape

This is specialization with extension.

7. Key Points
 Overloading vs Overriding
o Overloading = Same name, different parameters (compile-time polymorphism).
o Overriding = Same name, same parameters, redefined in derived (runtime
polymorphism).
 Virtual functions ensure correct overriding behavior.
 override keyword (C++11) → helps compiler check correctness.
 Access specifiers (public, protected, private) control visibility of overridden
functions.
 Overriding = specialization → derived class provides more specific behavior.

8. Real-Life Analogy
 Base class: "Vehicle" with function move().
 Derived classes:
o Car::move() → "Drives on road".
o Boat::move() → "Sails on water".
o Airplane::move() → "Flies in the sky".

Same function name, specialized behavior depending on object.

Final Takeaway

 Overriding lets derived classes specialize base class behavior.


 Access control allows changing the visibility of overridden functions.
 Used with virtual functions + inheritance to achieve runtime polymorphism.
Polymorphism in C++
1. Introduction
The word polymorphism comes from Greek:

 Poly = many
 Morph = forms

In C++ OOP, polymorphism means "one interface, many implementations."


A single function/operator/statement can behave differently depending on the context.

2. Types of Polymorphism in C++


Polymorphism is broadly divided into two categories:

1. Compile-time Polymorphism (Static Binding / Early Binding)

 Decision made at compile-time.


 Achieved by:
o Function Overloading
o Operator Overloading
o Template functions (generic polymorphism)

2. Runtime Polymorphism (Dynamic Binding / Late Binding)

 Decision made at runtime.


 Achieved by:
o Function Overriding (with virtual functions).
o Base class pointer/reference pointing to derived object.

3. Compile-time Polymorphism Examples


Example 1: Function Overloading
#include <iostream>
using namespace std;

class Print {
public:
void show(int x) {
cout << "Integer: " << x << endl;
}
void show(double y) {
cout << "Double: " << y << endl;
}
void show(string s) {
cout << "String: " << s << endl;
}
};

int main() {
Print p;
[Link](10); // Integer
[Link](3.14); // Double
[Link]("Hello"); // String
return 0;
}

Same function show, but works differently based on argument type.

Example 2: 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 display() {
cout << real << " + " << imag << "i" << endl;
}
};

int main() {
Complex c1(3,4), c2(1,2);
Complex c3 = c1 + c2; // Uses overloaded +
[Link](); // 4 + 6i
return 0;
}

4. Runtime Polymorphism Example


Example 3: Function Overriding (Virtual Functions)
#include <iostream>
using namespace std;

class Animal {
public:
virtual void sound() { // virtual = enable runtime polymorphism
cout << "Some generic animal sound" << endl;
}
};

class Dog : public Animal {


public:
void sound() override {
cout << "Bark!" << endl;
}
};

class Cat : public Animal {


public:
void sound() override {
cout << "Meow!" << endl;
}
};

int main() {
Animal* a; // Base class pointer

a = new Dog();
a->sound(); // Bark!

a = new Cat();
a->sound(); // Meow!

delete a;
return 0;
}

Here:

 Compile-time cannot decide which sound() to call.


 At runtime, the function call is resolved dynamically.

5. Polymorphism Diagram
Polymorphism
/ \
Compile-time Runtime
(Early Binding) (Late Binding)
----------------- -----------------
- Function Overloading - Virtual Functions
- Operator Overloading - Function Overriding
- Templates
6. Real-Life Analogies
 Compile-time Polymorphism → “Power button”
o On TV → turns it on.
o On Laptop → boots the system.
o On Fan → starts the motor.
Same "action" but compiler decides based on context (device).
 Runtime Polymorphism → “MakeSound()” for Animals
o Dog → Bark.
o Cat → Meow.
o Cow → Moo.
Same "function" but decided at runtime depending on object type.

7. Key Points
 Compile-time polymorphism = overloading & templates.
 Runtime polymorphism = overriding with virtual functions.
 Virtual functions enable dynamic dispatch.
 Polymorphism increases flexibility, reusability, and scalability of code.

8. Quick Comparison: Overloading vs Overriding


Feature Overloading (Compile-time) Overriding (Runtime)
Same name & params in base &
Definition Same name, different params
derived
Binding Early (compile-time) Late (runtime)
Keyword
No virtual, override
needed?
add(int,int),
Example add(double,double)
Animal::sound() overridden in Dog

Final Takeaway

 Polymorphism = Same name, different forms.


 Compile-time polymorphism → Overloading, templates.
 Runtime polymorphism → Overriding with virtual functions.
 It is the heart of OOP because it enables flexibility and code reuse.
Virtual Functions in C++
1. Introduction
In normal inheritance, when a base class pointer points to a derived object, the function call is
resolved at compile-time (static binding).
But sometimes we want the derived class version to run at runtime.

That’s where virtual functions come in.

Definition:
A virtual function is a member function in a base class declared with the keyword virtual,
which allows it to be overridden in derived classes and ensures runtime (dynamic)
polymorphism.

2. Syntax
class Base {
public:
virtual void display() { // virtual function
cout << "Base display" << endl;
}
};

class Derived : public Base {


public:
void display() override { // overriding
cout << "Derived display" << endl;
}
};

3. Example 1: Without Virtual Function


#include <iostream>
using namespace std;

class Base {
public:
void show() { // NOT virtual
cout << "Base show()" << endl;
}
};

class Derived : public Base {


public:
void show() { // overrides, but NOT virtual
cout << "Derived show()" << endl;
}
};

int main() {
Base* b;
Derived d;
b = &d;

b->show(); // Output: Base show() (static binding!)


return 0;
}

Even though b points to a Derived object, base version is called.

4. Example 2: With Virtual Function


#include <iostream>
using namespace std;

class Base {
public:
virtual void show() { // Virtual function
cout << "Base show()" << endl;
}
};

class Derived : public Base {


public:
void show() override { // Overrides base
cout << "Derived show()" << endl;
}
};

int main() {
Base* b;
Derived d;
b = &d;

b->show(); // Output: Derived show() (runtime polymorphism!)


return 0;
}

With virtual, the correct function (Derived::show) is executed at runtime.

5. Key Rules of Virtual Functions


1. Declared with virtual keyword in the base class.
2. Enable runtime polymorphism (dynamic binding).
3. If a derived class overrides it, derived version runs (when accessed through base
pointer/reference).
4. Base class pointer/reference required for runtime polymorphism.
5. If not overridden → base class version executes.
6. Can only be member functions of a class (not standalone).
7. Constructors cannot be virtual, but destructors should often be virtual.
8. A class with a virtual function has a vtable (virtual table) created internally by the
compiler.

6. Example 3: Polymorphic Behavior


#include <iostream>
using namespace std;

class Animal {
public:
virtual void sound() { cout << "Some generic sound" << endl; }
};

class Dog : public Animal {


public:
void sound() override { cout << "Bark!" << endl; }
};

class Cat : public Animal {


public:
void sound() override { cout << "Meow!" << endl; }
};

int main() {
Animal* a;

a = new Dog();
a->sound(); // Bark!

a = new Cat();
a->sound(); // Meow!

delete a;
return 0;
}

7. Virtual Destructors
When using inheritance with dynamic memory, destructors in the base class should be virtual,
otherwise only the base destructor runs, causing memory leaks.
Example 4: Without Virtual Destructor
#include <iostream>
using namespace std;

class Base {
public:
~Base() { cout << "Base Destructor" << endl; }
};

class Derived : public Base {


public:
~Derived() { cout << "Derived Destructor" << endl; }
};

int main() {
Base* b = new Derived();
delete b; // Only Base destructor runs!
return 0;
}

Example 5: With Virtual Destructor


#include <iostream>
using namespace std;

class Base {
public:
virtual ~Base() { cout << "Base Destructor" << endl; }
};

class Derived : public Base {


public:
~Derived() { cout << "Derived Destructor" << endl; }
};

int main() {
Base* b = new Derived();
delete b; // Derived + Base destructor run (correct)
return 0;
}

8. Real-Life Analogy
 Base class: Shape with draw().
 Derived classes:
o Circle::draw() → Draws circle.
o Rectangle::draw() → Draws rectangle.
With virtual draw(), the correct shape gets drawn at runtime, even if we handle all objects
via a Shape* pointer.

9. Key Differences: Normal vs Virtual Function


Feature Normal Function Virtual Function
Binding Compile-time Runtime
Keyword None virtual
Overriding Not polymorphic Supports polymorphism
Use case General functions When derived must specialize behavior

Final Takeaway

 Virtual functions enable runtime polymorphism.


 Declared in base class with virtual.
 Overridden in derived class with same signature.
 Use virtual destructors in base classes to prevent memory leaks.
Abstract Classes and Virtual Function Tables
in C++

1. Abstract Classes
Definition

An abstract class in C++ is a class that cannot be instantiated and is meant only to be a base
class for other classes.
It contains at least one pure virtual function.

Pure Virtual Function

A pure virtual function is declared like this:

virtual void functionName() = 0;

 = 0 makes it pure virtual.


 Derived classes must override it; otherwise, they too become abstract.

Example 1: Abstract Class


#include <iostream>
using namespace std;

class Shape {
public:
virtual void draw() = 0; // Pure virtual function
};

class Circle : public Shape {


public:
void draw() override {
cout << "Drawing Circle" << endl;
}
};

class Square : public Shape {


public:
void draw() override {
cout << "Drawing Square" << endl;
}
};
int main() {
// Shape s; ❌ Error: abstract class
Shape* s;

s = new Circle();
s->draw(); // Drawing Circle

s = new Square();
s->draw(); // Drawing Square

delete s;
return 0;
}

Here:

 Shape is abstract.
 It forces derived classes (Circle, Square) to implement draw().
 Achieves runtime polymorphism.

Key Features of Abstract Classes

1. Cannot create objects of abstract class.


2. Can have constructors & normal functions.
3. Can contain data members.
4. Derived classes must override pure virtual functions.
5. Supports interface-like behavior.

2. Virtual Function Table (vtable)


Why vtable?

When we use virtual functions, C++ needs a mechanism to decide at runtime which function to
call (base or derived).
This mechanism is the vtable (virtual table).

How vtable Works

1. For every class with virtual functions, the compiler creates a vtable.
2. The vtable is basically an array of function pointers.
3. Each object of the class stores a hidden vptr (virtual pointer) that points to its class’s
vtable.
4. When a virtual function is called via a base pointer, the program looks up the function
address from the vtable.

Example 2: vtable Visualization


#include <iostream>
using namespace std;

class Base {
public:
virtual void show() { cout << "Base show()" << endl; }
virtual void print() { cout << "Base print()" << endl; }
};

class Derived : public Base {


public:
void show() override { cout << "Derived show()" << endl; }
void print() override { cout << "Derived print()" << endl; }
};

int main() {
Base* b;
Derived d;

b = &d;
b->show(); // Derived show()
b->print(); // Derived print()
return 0;
}

vtable Representation (simplified)

 Base class vtable

Base vtable:
show() --> Base::show
print() --> Base::print

 Derived class vtable

Derived vtable:
show() --> Derived::show
print() --> Derived::print

 b = &d;
o b->show() → looks up Derived::show in derived’s vtable.
o b->print() → looks up Derived::print.
3. Example 3: Partial Overriding
If a derived class overrides only one function, its vtable contains a mix:

class Derived2 : public Base {


public:
void show() override { cout << "Derived2 show()" << endl; }
// print() not overridden → inherits Base::print
};

Derived2’s vtable:

show() --> Derived2::show


print() --> Base::print

4. Real-Life Analogy
 Abstract Class: Think of it like a blueprint (House plan). You can’t "live" in a blueprint
directly, but you can build real houses (derived classes) from it.
 vtable: Think of it as a directory of contacts. When you call a function, C++ checks the
right address in the "directory" (vtable) depending on the object’s actual type.

5. Key Points to Remember


 Abstract class = has at least one pure virtual function.
 Used to enforce a contract in derived classes.
 Virtual function table (vtable) = compiler-generated lookup table for runtime
polymorphism.
 vptr = hidden pointer in every object that points to its vtable.
 Function call resolution happens via vtable at runtime.

Final Takeaway

 Abstract classes → define what must be done but not how.


 Derived classes → provide actual implementation.
 vtable → mechanism that enables runtime polymorphism in C++.
Introduction to Pointers in C++

1. What is a Pointer?
A pointer is a special type of variable that stores the memory address of another variable.

Instead of holding a value directly, it points to the location where the value is stored.

2. Why Use Pointers?


 Efficient memory management.
 Dynamic memory allocation (new, delete).
 To pass variables by reference (avoid copying).
 To create data structures like linked lists, trees, graphs.
 For polymorphism (base class pointer → derived object).

3. Pointer Declaration & Syntax


dataType* pointerName;

 dataType → type of variable the pointer will point to.


 * → denotes that it is a pointer.

Example 1: Basic Pointer


#include <iostream>
using namespace std;

int main() {
int x = 10;
int* ptr = &x; // pointer stores address of x

cout << "Value of x: " << x << endl;


cout << "Address of x: " << &x << endl;
cout << "Pointer ptr stores: " << ptr << endl;
cout << "Value at ptr (dereferencing): " << *ptr << endl;

return 0;
}

Output (example):

Value of x: 10
Address of x: 0x61ff0c
Pointer ptr stores: 0x61ff0c
Value at ptr (dereferencing): 10

4. Important Operators
 & (Address-of operator) → gives the address of a variable.
 * (Dereference operator) → accesses the value stored at a pointer’s address.

5. Pointer Types in C++


1. Null Pointer

A pointer initialized to nullptr (points to nothing).

int* p = nullptr;

2. Void Pointer

Generic pointer that can point to any type.

void* p;
int a = 5;
p = &a;

3. Pointer to Pointer

A pointer that stores the address of another pointer.

int x = 5;
int* p = &x;
int** pp = &p;
cout << **pp; // 5

4. Wild Pointer

Uninitialized pointer (points to random memory) → Dangerous!

int* p; // uninitialized
*p = 10; // ❌ Undefined behavior

5. Dangling Pointer

Pointer pointing to memory that has been freed/deleted.

int* p = new int(10);


delete p;
p = nullptr; // prevent dangling pointer

6. Example 2: Pointer Arithmetic


#include <iostream>
using namespace std;

int main() {
int arr[3] = {10, 20, 30};
int* p = arr;

cout << *p << endl; // 10


cout << *(p + 1) << endl; // 20
cout << *(p + 2) << endl; // 30

return 0;
}

Pointers can be incremented/decremented to move across array elements.

7. Example 3: Passing by Pointer


#include <iostream>
using namespace std;

void update(int* p) {
*p = *p + 5; // modifies original value
}

int main() {
int x = 10;
update(&x);
cout << "Updated x: " << x << endl; // 15
return 0;
}

8. Real-Life Analogy
 Variable = House (stores value = furniture).
 Address = House Number.
 Pointer = Person carrying the house number (knows where the furniture is).
 Dereferencing = Going to the house and checking the furniture.

9. Key Points
 Pointers hold addresses, not values.
 Use * to dereference (access the value).
 Use & to get a variable’s address.
 Always initialize pointers (nullptr).
 Be careful of wild and dangling pointers.
 Pointers are powerful but need careful handling (manual memory).

Final Takeaway

 A pointer = variable storing address.


 Used for efficient memory use, dynamic allocation, and data structures.
 Supports polymorphism and function parameter passing in C++.
Pointers to Pointers in C++

1. Introduction
A pointer to pointer (also called double pointer) is a pointer that stores the address of another
pointer.

Instead of pointing directly to a variable, it points to a pointer that points to the variable.

2. Syntax
dataType** ptr2;

 ptr2 is a pointer to a pointer of type dataType.


 One * = pointer to data.
 Two * = pointer to pointer (address of another pointer).

3. Memory Diagram
int x = 10;
int* p = &x; // pointer to int
int** pp = &p; // pointer to pointer

Representation:

x = 10
p = address of x (&x)
pp = address of p (&p)

So:

 x → 10
 *p → 10
 *pp → address of x
 **pp → 10
4. Example 1: Basic Pointer to Pointer
#include <iostream>
using namespace std;

int main() {
int x = 42;
int* p = &x; // pointer to int
int** pp = &p; // pointer to pointer

cout << "Value of x: " << x << endl;


cout << "Value using *p: " << *p << endl;
cout << "Value using **pp: " << **pp << endl;

cout << "Address of x: " << &x << endl;


cout << "Pointer p stores: " << p << endl;
cout << "Pointer pp stores: " << pp << endl;

return 0;
}

Output (example):

Value of x: 42
Value using *p: 42
Value using **pp: 42
Address of x: 0x61ff08
Pointer p stores: 0x61ff08
Pointer pp stores: 0x61ff04

5. Example 2: Modifying Value Using Pointer to Pointer


#include <iostream>
using namespace std;

int main() {
int x = 5;
int* p = &x;
int** pp = &p;

cout << "Before: " << x << endl;

**pp = 20; // modifying x via double pointer

cout << "After: " << x << endl;


return 0;
}

Output:

Before: 5
After: 20
**pp gives access to x.

6. Example 3: Function with Double Pointer


Pointers to pointers are often used in functions to modify pointers themselves (not just the
values they point to).

#include <iostream>
using namespace std;

void allocateMemory(int** pp) {


*pp = new int; // allocate memory dynamically
**pp = 100; // assign value
}

int main() {
int* p = nullptr;

allocateMemory(&p); // passing pointer to pointer


cout << "Value stored: " << *p << endl;

delete p; // free memory


return 0;
}

7. Example 4: Pointers to Pointers with Arrays


#include <iostream>
using namespace std;

int main() {
int arr[3] = {10, 20, 30};
int* p = arr; // pointer to first element
int** pp = &p; // pointer to pointer

cout << "First element: " << **pp << endl; // 10

p++; // move pointer to next element


cout << "Second element: " << **pp << endl; // 20

return 0;
}

8. Real-Life Analogy
 Variable = House (stores value).
 Pointer = Person with house address.
 Pointer to Pointer = Person who knows the person holding the house address.

Indirect access, but still leads to the original house (value).

9. Key Points
 * = single pointer → stores address of variable.
 ** = double pointer → stores address of a pointer.
 Useful in:
o Dynamic memory allocation.
o Passing pointers to functions.
o Multi-dimensional arrays.
o Complex data structures (linked lists, trees, graphs).

Final Takeaway

 A pointer to pointer stores address of another pointer.


 **pp gives direct access to the original variable’s value.
 Useful in memory management and functions needing reference to a pointer.
Pointers and String Arrays in C++

1. Introduction
 A string in C++ can be represented in two ways:
1. C-style string → Character array ending with '\0'.
2. C++ string class (std::string).
 Pointers make it possible to work with string arrays efficiently by directly pointing to
characters or arrays of strings.

2. Strings as Character Arrays


#include <iostream>
using namespace std;

int main() {
char str1[] = "Hello"; // stored as array of chars
char* str2 = "World"; // pointer to string literal

cout << str1 << endl; // Hello


cout << str2 << endl; // World

return 0;
}

str1 is an array (modifiable).


str2 is a pointer to a string literal (read-only in modern C++).

3. Accessing Characters Using Pointers


#include <iostream>
using namespace std;

int main() {
char str[] = "Pointer";

char* p = str; // p points to first character

cout << *p << endl; // P


cout << *(p + 1) << endl; // o
cout << *(p + 2) << endl; // i
return 0;
}

Pointers can move across the characters of a string.

4. Array of Strings Using 2D Character Array


#include <iostream>
using namespace std;

int main() {
char fruits[3][10] = {"Apple", "Banana", "Cherry"};

for (int i = 0; i < 3; i++) {


cout << fruits[i] << endl;
}
return 0;
}

Here, fruits is a 2D array of characters.

 Each row = one string.


 Memory is contiguous.

5. Array of Strings Using Array of Pointers


#include <iostream>
using namespace std;

int main() {
const char* fruits[] = {"Apple", "Banana", "Cherry"};

for (int i = 0; i < 3; i++) {


cout << fruits[i] << endl;
}
return 0;
}

Each element of fruits[] is a pointer to a string literal.


Memory is non-contiguous (each string stored separately, only addresses stored in array).
6. Difference Between 2D Char Array vs Array of Pointers
Feature 2D Char Array (char arr[3][10]) Array of Pointers (char* arr[])
Memory layout Contiguous block Non-contiguous (pointers to literals)
Modifiable? Yes (strings can be changed) No (string literals are read-only)
Flexibility Fixed size (max length set) Flexible (strings of different lengths)

7. Example: Modifying String with Pointers


#include <iostream>
using namespace std;

int main() {
char str[] = "Hello";
char* p = str;

*p = 'M'; // change first char


cout << str << endl; // Mello

return 0;
}

Works because str is an array (modifiable).

If you try the same with char* p = "Hello"; → it’s undefined behavior, because string
literals are read-only.

8. Example: Pointer to String Array


#include <iostream>
using namespace std;

int main() {
const char* cities[] = {"London", "Paris", "Tokyo", "New York"};
const char** p = cities; // pointer to array of string pointers

cout << *p << endl; // London


cout << *(p + 1) << endl; // Paris
cout << *(p + 2) << endl; // Tokyo

return 0;
}

const char** p → pointer to pointer to char (points to array of string pointers).


9. Real-Life Analogy
 2D char array → like a hostel with fixed-size rooms (each student = character, each
room = string).
 Array of string pointers → like a guest list (each entry is just an address where a person
is staying).

10. Key Points


 Strings can be represented as character arrays or pointers to char.
 Array of strings can be stored:
o As 2D char array (contiguous).
o As array of string pointers (non-contiguous).
 Pointers allow iteration, modification, and dynamic handling of strings.
 C++ std::string is safer and recommended, but understanding pointers + string arrays
is crucial for C-style programming and memory management.

Final Takeaway

 Pointers and string arrays are deeply connected since strings in C are just character
arrays with \0 terminator.
 Using pointers makes string handling efficient and flexible, but also requires careful
memory management.
Void Pointers and Function Pointers in C++

1. Void Pointers (void*)


Definition

A void pointer (also called a generic pointer) is a special pointer that can store the address of
any data type, but it cannot be dereferenced directly without typecasting.

Syntax
void* ptr;

Example 1: Using Void Pointer


#include <iostream>
using namespace std;

int main() {
int a = 10;
double b = 5.5;
char c = 'Z';

void* ptr;

ptr = &a;
cout << "Integer: " << *(int*)ptr << endl;

ptr = &b;
cout << "Double: " << *(double*)ptr << endl;

ptr = &c;
cout << "Char: " << *(char*)ptr << endl;

return 0;
}

Output:

Integer: 10
Double: 5.5
Char: Z
void* can point to any type, but we must cast before dereferencing.

Key Points about Void Pointers

 Universal pointer (can point to any type).


 Cannot be dereferenced directly.
 Commonly used in generic functions, memory management, and dynamic allocation.

Real-Life Analogy

Imagine void* as a locker that can hold any type of object, but before using it, you must open it
with the right key (typecasting).

2. Function Pointers
Definition

A function pointer is a pointer that stores the address of a function.


This allows us to:

 Call functions indirectly.


 Pass functions as arguments to other functions (like callbacks).
 Implement dynamic function selection.

Syntax
returnType (*ptrName)(parameterTypes);

Example 1: Basic Function Pointer


#include <iostream>
using namespace std;

void greet() {
cout << "Hello from function!" << endl;
}

int main() {
void (*fp)(); // function pointer declaration
fp = &greet; // assign address of function

fp(); // call function using pointer


(*fp)(); // alternative way

return 0;
}

Output:

Hello from function!


Hello from function!

Example 2: Function Pointer with Parameters


#include <iostream>
using namespace std;

int add(int a, int b) {


return a + b;
}

int multiply(int a, int b) {


return a * b;
}

int main() {
int (*fp)(int, int); // function pointer declaration

fp = add;
cout << "Sum: " << fp(5, 3) << endl; // 8

fp = multiply;
cout << "Product: " << fp(5, 3) << endl; // 15

return 0;
}

Example 3: Passing Function Pointers to Functions


#include <iostream>
using namespace std;

void compute(int a, int b, int (*operation)(int, int)) {


cout << "Result: " << operation(a, b) << endl;
}
int add(int x, int y) { return x + y; }
int sub(int x, int y) { return x - y; }

int main() {
compute(10, 5, add); // Result: 15
compute(10, 5, sub); // Result: 5
return 0;
}

Useful in callbacks, event handling, sorting functions (like qsort in C).

Function Pointer Arrays

We can store multiple function pointers in an array for menu-driven programs.

#include <iostream>
using namespace std;

int add(int a, int b) { return a + b; }


int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }

int main() {
int (*ops[])(int, int) = {add, sub, mul};

cout << "Addition: " << ops[0](5, 3) << endl;


cout << "Subtraction: " << ops[1](5, 3) << endl;
cout << "Multiplication: " << ops[2](5, 3) << endl;

return 0;
}

3. Key Differences Between Void Pointers and Function


Pointers
Feature Void Pointer (void*) Function Pointer
Purpose Stores address of any data type Stores address of a function
Dereferencing Requires typecasting Used to call functions
Use cases Generic programming, memory allocation Callbacks, dynamic dispatch
Example Syntax void* p; int (*fp)(int,int);

Final Takeaway
 Void Pointers = Generic pointers → can point to any type (must typecast before use).
 Function Pointers = Special pointers → store function addresses, enabling indirect
function calls and callbacks.
Standard Template Library (STL) in C++

1. Introduction
The Standard Template Library (STL) in C++ is a collection of predefined classes and
functions that implement common data structures and algorithms.

It saves time because you don’t have to write everything from scratch.

2. Components of STL
STL has 4 major components:

1. Algorithms – Predefined functions for searching, sorting, counting, etc.


2. Containers – Data structures to store collections of data.
3. Iterators – Objects that point to elements in containers (like pointers).
4. Functors – Function objects used with algorithms.

3. Containers in STL
Containers are objects that store data.
They are divided into three categories:

3.1 Sequence Containers

 Store data in linear order.


 Examples:
o vector (dynamic array)
o list (doubly linked list)
o deque (double-ended queue)
o array (fixed-size array wrapper)
o forward_list (singly linked list)

#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> v = {1, 2, 3, 4};
v.push_back(5); // add at end

for (int x : v) cout << x << " ";


return 0;
}

3.2 Associative Containers

 Store data in key-value form.


 Automatically sorted by keys.
 Examples:
o set – stores unique elements
o multiset – stores duplicate elements
o map – key-value pairs (unique keys)
o multimap – key-value pairs (duplicate keys allowed)

#include <iostream>
#include <map>
using namespace std;

int main() {
map<int, string> students;
students[101] = "Alice";
students[102] = "Bob";

for (auto p : students) {


cout << [Link] << " -> " << [Link] << endl;
}
return 0;
}

3.3 Unordered Containers

 Store data in hash tables.


 Faster (average O(1) lookup).
 Examples:
o unordered_set
o unordered_multiset
o unordered_map
o unordered_multimap

#include <iostream>
#include <unordered_set>
using namespace std;

int main() {
unordered_set<int> s = {1, 2, 3, 2, 1};
for (int x : s) cout << x << " "; // order not guaranteed
return 0;
}

4. Iterators
 Iterators act like pointers to container elements.
 Types:
o Input iterators
o Output iterators
o Forward iterators
o Bidirectional iterators
o Random access iterators

#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> v = {10, 20, 30};

vector<int>::iterator it;
for (it = [Link](); it != [Link](); ++it) {
cout << *it << " ";
}
return 0;
}

5. Algorithms
STL provides many ready-to-use algorithms inside <algorithm> header.

Examples:

 sort([Link](), [Link]())
 reverse([Link](), [Link]())
 count([Link](), [Link](), 5)
 find([Link](), [Link](), 10)
 binary_search([Link](), [Link](), key)

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
vector<int> v = {5, 2, 8, 1, 3};
sort([Link](), [Link]());
for (int x : v) cout << x << " ";
return 0;
}

6. Functors
 A functor is a class that overloads the () operator, making objects callable like
functions.
 Used with STL algorithms for custom behavior.

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct Square {
void operator()(int x) {
cout << x * x << " ";
}
};

int main() {
vector<int> v = {1, 2, 3};
for_each([Link](), [Link](), Square());
return 0;
}

7. Why Use STL?


✔ Reduces coding effort (pre-built).
✔ Optimized for performance.
✔ Reusable and generic.
✔ Safer and less error-prone than writing custom data structures.

8. Real-Life Analogy
Think of STL as a toolbox:

 Containers = different types of boxes to store items.


 Iterators = hands/tools to access items in boxes.
 Algorithms = machines/tools to sort, search, or process items.
 Functors = custom tools you can design yourself.
Final Takeaway
 STL = Algorithms + Containers + Iterators + Functors.
 Provides efficient, reusable, and standardized implementations.
 Mastering STL is essential for competitive programming, interviews, and real-world
C++ development.

Would you like me to prepare a topic-wise coding exercise sheet (like small tasks using
vector, set, map, etc.) so your students can practice STL hands-on?

You might also like