[go: up one dir, main page]

0% found this document useful (0 votes)
10 views38 pages

Module - 1

This document outlines the first module of a course on Data Structures using C++, focusing on software engineering principles and C++ classes. It covers the software life cycle, phases of software development, and key concepts in object-oriented design such as classes, constructors, and UML diagrams. The module aims to equip students with the ability to apply OOD principles, manage dynamic memory, and effectively use pointers in C++.

Uploaded by

manishm512007
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)
10 views38 pages

Module - 1

This document outlines the first module of a course on Data Structures using C++, focusing on software engineering principles and C++ classes. It covers the software life cycle, phases of software development, and key concepts in object-oriented design such as classes, constructors, and UML diagrams. The module aims to equip students with the ability to apply OOD principles, manage dynamic memory, and effectively use pointers in C++.

Uploaded by

manishm512007
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
You are on page 1/ 38

Data Structures using C++

Department of Electronics & Communication


CEC, Mangalore
Module-1 : Software Engineering Principles And C++ Classes

Table of contents

Software Life Cycle


Software Development Phase
Classes:
Constructors
Unified Modeling Language Diagrams
Variable (Object) Declaration
Accessing Class Members
Implementation of Member Functions
Reference Parameters and Class Objects (Variables)
Assignment Operator and Classes
Class Scope
Functions and Classes
Constructors and Default Parameters
Destructors
Structs
OOD:
Inheritance,
Polymorphism,
Templates

Objectives
The objectives of this Module are to:
Understand the software life cycle and various software development phases. Learn the fundamentals of C++ classes and object-oriented design
(OOD) principles. Explore inheritance, polymorphism, and templates to create reusable and modular code. Master the use of pointers and pointer
variables in C++. Understand the relationship between classes and pointers, including inheritance pointers and virtual functions. Learn about
abstract classes and pure virtual functions. Implement array-based lists and manage dynamic memory.

Learning outcome
On completion of this Module, you will be able to:
Understand the software life cycle, software development phases
Apply object-oriented design principles using C++ classes.
Effectively use pointers and array-based lists, and understand their applications in dynamic memory management and class relationships
Session :1
Software Life Cycle, Software Development Phase, Classes: Constructors, Unified Modelling Language Diagrams, Variable (Object) Declaration, Accessing Class Members,
Implementation of Member Functions,

1. Software life cycle


The life cycle of a software program consists of :
1. Development:
• A software program is conceived by a developer to solve a customer’s problem.
• During development, the program is created, coded, and tested.
• Example: Creating a travel app to help users find flights and book hotels.
2. Use:
• Once complete, the program is released for users to use.
• Users provide feedback, discover issues, and suggest improvements.
• Example: Users start using the travel app, encountering features and reporting issues.
3. Maintenance:
• In this phase, the program is modified to fix identified problems or enhance it.
• Developers address user feedback, apply patches, and release updates.
• Example: Fixing bugs, adding new features, and improving performance.
4. Retirement:
• If maintenance becomes too expensive, the developer may retire the program.
• No new versions are released, and support ends.
• Example: Deciding to retire an outdated app due to cost constraints.
The life cycle ensures continuous improvement and adaptation to user needs.
2. Software Development Phase
Software development typically follows a structured process known as the Software Development Life
Cycle (SDLC). This cycle consists of several phases, each with specific tasks and objectives. Let’s delve
into these four key phases:
5. Requirements Analysis:
o Purpose: In the initial planning phase, the team defines the software’s purpose and scope. It’s
like plotting the best route for a journey. This phase identifies and records precise user
requirements.
o Tasks:
▪ Gather information from stakeholders (users, analysts, clients).
▪ Conduct interviews, surveys, and focus groups.
o Example: For our travel app, we’d collect requirements like search filters (dates, destinations),
payment options, and user profiles.
6. Design:
o Purpose: Sketch out how the software will be implemented.
o Tasks:
▪ Create high-level and detailed designs (architecture, user interfaces, data flow).
▪ Decide on technologies, frameworks, and components.
o Example: Design the app’s layout, navigation, and database structure. Choose whether to use
React or Angular for the front end.
7. Implementation:
o Purpose: Write actual code based on the design.
o Tasks:
▪ Develop features and modules.
▪ Follow coding standards and best practices.
o Example: Write code for flight search algorithms, user authentication, and payment
processing.
8. Testing and Debugging:
o Purpose: Ensure the software functions correctly and identify and fix any issues.
o Tasks:
▪ Conduct unit testing, integration testing, and system testing.
▪ Debug and resolve defects.
o Example: Test the app by booking a flight, checking if the payment gateway works, and fixing
any glitches.
Remember, these phases are interconnected, and successful software development involves
collaboration, iteration, and continuous improvement.
3. Classes:
o A class serves as a blueprint or template in object-oriented programming (OOP). It
defines the structure and behavior of objects.
▪ Attributes: A class has attributes (also called properties or fields) that represent
the data associated with objects of that class. For example, in your “Car” class:
▪ “make” and “model” are attributes representing the car’s manufacturer
and model name.
▪ Methods: A class also contains methods (functions) that define the behavior or
actions that objects can perform. In your “Car” class:
▪ “start_engine()” and “drive()” are methods that allow you to start the car’s
engine and drive it.
▪ Object Instances: You create instances (objects) of a class based on its blueprint.
Each instance has its own set of attribute values.
▪ Example :
#include <iostream>
using namespace std;
class Car {
public:
// Attributes
string make;
string model;
// Methods
void start_engine() {
cout << "Starting the engine..." << endl;
}
void drive() {
cout << "Driving the car..." << endl;
}
};

int main() {
Car my_car;
my_car.make ="BMW";
my_car.model = "A100";
cout << my_car.make << endl; // Output: "Toyota"
return 0;
}

4. Constructors:
A constructor is a special method within
a class that initializes object instances Example :
#include <iostream>
when they are created. using namespace std;
Key points: class Car {
public:
❖ Purpose: Constructors set initial values for the
string make;
object’s attributes.
string model;
❖ Name: Constructors have the same name as the
class (usually __init__ in Python). // Constructor
❖ Parameters: The constructor takes parameters (often Car(string make, string model){
including self as the first parameter) to assign this->make = make;
values to attributes. this->model = model;
}
};
int main() {
Car my_car("Toyota", "Camry");
return 0;
}
5. Unified Modeling Language (UML) Diagrams:
What is UML?
o Unified Modeling Language (UML) is a standardized visual modeling language used in
software engineering.
o Its purpose is to provide a general-purpose, intuitive way to visualize system designs.
o UML helps specify, visualize, construct, and document software artifacts.
o It’s not a programming language; rather, it’s a visual language for modeling systems.
Why do we need UML?
o Complex applications involve collaboration among multiple teams, requiring clear
communication.
o UML allows us to communicate system requirements, functionalities, and processes
effectively.
o It saves time by visualizing processes, user interactions, and system structures.
Types of UML Diagrams:
UML includes various diagram types. Let’s focus on class diagrams:
o Class Diagrams: These depict the static structure of a system by showing classes,
their attributes, and methods.
o Class diagrams help identify relationships between different classes or objects.
Elements in Class Diagrams:
o Classes: Represent entities (e.g., “Account,” “Customer”) with attributes and methods.
o Attributes: Describe properties of classes (e.g., “balance” for an Account).
o Methods: Define behavior or actions (e.g., “withdraw()” for an Account).
o Associations: Show logical connections between classes (e.g., “Account” and
“Customer”).
o Relationships: Describe how classes interact.
Common Relationships in Class Diagrams:
o Association: Broad term for any logical connection between classes.
o Directed Association: Represents a directional relationship (e.g., “passenger” and
“airline”).
o Reflexive Association: When a class has multiple functions or responsibilities (e.g.,
staff roles at an airport).
o Multiplicity: Depicts cardinality (e.g., one fleet has multiple airplanes).
o Aggregation: Forms a class from aggregated components (e.g., “library” composed of
books).
o Composition: Similar to aggregation but emphasizes strong dependence (e.g., shoulder
bag and its pocket).
Example: Banking System Class Diagram:
Let’s create a simple class diagram for a banking system:
 Classes: “Account,” “Customer”
 Attributes: “Account” has “balance,” “Customer” has “name”
 Methods: “Account” has “withdraw()” and “deposit()”
 Associations: “Account” associated with “Customer”

UML class diagrams provide a powerful way to visualize & communicate system designs
6. Variable (Object) Declaration: in the context of class objects:
Class Objects:
o After defining a class, you can declare variables of that class type.
o In C++ terminology, a class variable is often called a class object or class instance.
o For simplicity, we’ll use the term object to refer to a class variable.
o An object holds an instance of the class, allowing you to work with its properties and
methods.
Syntax for Object Declaration:
o To declare an object that invokes the default constructor, use this syntax:
o className classObjectName;
Example:
clockType myClock; // Creates an object of type clockType
The default constructor initializes instance variables to their default values (usually 0).
Avoid Empty Parentheses: If you want the default constructor to execute, omit the empty
parentheses after the object name. Including empty parentheses accidentally results in a
syntax error.
// Incorrect: Generates a syntax error
clockType myClock(); // Illegal object declaration
Parameterized Constructors:
A class can have two types of constructors:
▪ Default constructor: Executes when you create an object without passing any
arguments.
▪ Constructors with parameters: Execute when you provide specific arguments
during object creation.
When you declare a class object, either the default constructor or a parameterized
constructor executes.
To declare an object that invokes a constructor with parameters, use this syntax:
className classObjectName(argument1, argument2, ...);
▪ Each argument can be a variable or an expression.
Understanding object declaration is crucial for working with class instances!
#include <iostream>
class ClockType {
public:
// Default constructor
ClockType() {
hours = 0;
minutes = 0;
}
// Parameterized constructor
ClockType(int h, int m) {
hours = h;
minutes = m;
}
void displayTime() {
std::cout << "Time: " << hours << ":" << minutes << std::endl;
}
private:
int hours;
int minutes;
};
int main() {
// Declare an object using the default constructor
ClockType myClock1;
myClock1.displayTime(); // Output: Time: 0:0
// Declare an object using the parameterized constructor
ClockType myClock2(10, 30);
myClock2.displayTime(); // Output: Time: 10:30
return 0;
}

In this example:`myClock1` is an object created using the default constructor, which initializes
hours and minutes to 0. `myClock2` is an object created using the parameterized constructor
with values 10 and 30 for hours and minutes, respectively.
7. Accessing Class Members:
In C++, you can access the attributes (data members) and methods (member functions) of a
class using the dot notation. This is done through an instance of the class, known as an
object.
Dot Notation: Used for accessing members through an object.
Arrow Operator (->): Used for accessing members through a pointer to an object.
Scope Resolution Operator (::): Used for accessing static members of a class.
Dot Notation
Syntax: object.attribute or object.method()
Example: If you have an object my_car of a class Car, you can call its method start_engine()
using my_car.start_engine().
Example Code
#include <iostream>
using namespace std;
class Car {
public:
string brand;
void start_engine() {
cout << "Engine started!" << endl;
}
};

int main() {
Car my_car;
my_car.brand = "Toyota";
my_car.start_engine(); // Calls the start_engine() method
// Accesses the brand attribute
cout << "Brand: " << my_car.brand << endl;
return 0;
}
Accessing Members via Pointers
When you have a pointer to an object, you use the arrow operator (->) to access its members.
Syntax: pointer->attribute or pointer->method()
Example:
Car* car_ptr = &my_car;
car_ptr->start_engine(); // Calls the start_engine() method via pointer
// Accesses the brand attribute via pointer
cout << "Brand: " << car_ptr->brand << endl;
Static Members
Static members belong to the class rather than any object instance. You access them using
the scope resolution operator (::).
Syntax: ClassName::static_member
Example:
class Car {
public:
static int total_cars;
static void show_total_cars() {
cout << "Total cars: " << total_cars << endl;
}
};
int Car::total_cars = 0;
int main() {
Car::total_cars = 5;
Car::show_total_cars(); // Calls the static method
return 0;
}
8. Implementation of Member Functions:
Member functions define the behavior of a class. They allow objects to perform specific
tasks or manipulate their internal state.
Implementation within the Class Definition:
Member functions can be implemented directly within the class definition.
Example:
class Rectangle {
private:
double length;
double width;

public:
// Member function implemented within the class definition
double calculate_area() {
return length * width;
}
};
Implementation Outside the Class Definition:
Member functions can also be implemented outside the class definition using the scope
resolution operator ::.
Example:
class Rectangle {
private:
double length;
double width;
public:
double calculate_area(); // Declaration of the member function
};
// Implementation of the member function outside the class
double Rectangle::calculate_area() {
return length * width;
}
Access Specifiers:
Member functions can be declared in different sections of the class: public, private, or
protected.
Public member functions can be accessed from outside the class.
Private member functions can only be accessed from within the class.
Protected member functions can be accessed from within the class and by derived classes.
Example: Implementing a calculate_area() Method in a Rectangle Class:
Let’s consider a Rectangle class that has a length and width. We want to calculate the area
of the rectangle.
Here is a complete example:
#include <iostream>
class Rectangle {
private:
double length;
double width;
public:
Rectangle(double l, double w) : length(l), width(w) {}

double calculate_area() const {


return length * width;
}
};
int main() {
Rectangle rect(5.0, 3.0);
std::cout << "Area of the rectangle: " << rect.calculate_area() << std::endl;
return 0;
}
In this example: The Rectangle class represents a rectangle with a length and width.
The calculate_area() member function computes the area of the rectangle. The main()
function demonstrates creating a Rectangle object and calculating its area.

Viva Questions:
1. Can you explain the different phases of the software life cycle and their importance?
2. How does user feedback influence the maintenance phase of the software life cycle?
3. What are the key activities involved in the requirements analysis phase of the SDLC?
4. How do you ensure that the design phase aligns with the requirements gathered?
5. What is a constructor in object-oriented programming, and why is it important?
6. Can you provide an example of a parameterized constructor and explain its use?
7. What are the different types of UML diagrams, and what purpose does each serve?
8. How do UML diagrams help in the software development process?
9. How do you declare an object in C++ or Python? Provide an example.
10. What is the difference between declaring a variable and initializing it?
11. How do you access public and private members of a class in C++?
12. Can you explain the concept of encapsulation with an example?

Theory Questions:
1. Describe the phases of the software life cycle with examples. How does each phase
contribute to the overall success of the software?
2. Explain the importance of the design phase in the SDLC. What are the key
deliverables produced during this phase?
3. Discuss the role of constructors in object-oriented programming. How do they differ
from regular methods?
4. What are UML diagrams, and why are they used in software engineering? Provide
examples of at least two types of UML diagrams.
5. Explain the process of declaring and initializing and accessing attributes of a
class/object in C++.
6. Describe the process of implementing member functions in a class. Provide an
example in C++.

Session :2
Reference Parameters and Class Objects (Variables), Assignment Operator and Classes, Class Scope, Functions and Classes, Constructors and Default Parameters,
Destructors, Structs
1. Reference Parameters and Class Objects (Variables):
Pass by Value:
When a variable is passed by value to a function, a copy of the variable’s value is made and
passed to the function. This means that any changes made to the parameter inside the
function do not affect the original variable.
Key Points:
❖ A copy of the variable is passed.
❖ Changes made inside the function do not affect the original variable.
❖ Commonly used for primitive data types like integers, floats, and characters.
Pass by Reference:
When a variable is passed by reference to a function, the function receives a reference to the
original variable. This means that any changes made to the parameter inside the function
will affect the original variable.
Key Points:
❖ A reference to the variable is passed.
❖ Changes made inside the function affect the original variable.
❖ Commonly used for objects and large data structures to avoid copying overhead.
Passing object as Reference:
When you pass a class object as a parameter to a function, it is passed by reference. This
means that the function receives a reference to the original object, not a copy of it. As a
result, any changes made to the object within the function will affect the original object. This
is different from passing primitive data types (like integers or floats), which are typically
passed by value, meaning a copy of the data is passed to the function.
Key Points:
❖ Pass by Reference: When a class object is passed to a function, the function operates on the original object.
No new copy of the object is created, which can save memory and processing time.
❖ Effect on Original Object: Any modifications made to the object within the function will reflect on the original
object. This is useful for functions that need to update or modify the state of an object.
Example:
Let’s consider a Person class with an attribute address. We will create a function that
updates the address of a Person object.
#include <iostream>
using namespace std;
class Person {
public:
string name;
string address;
Person(string n, string a) : name(n), address(a) {}
void display() {
cout << "Name: " << name << ", Address: " << address << endl;
}
};
// Function to update the address of a Person object
void updateAddress(Person &p, string newAddress) {
p.address = newAddress;
}
int main() {
Person person1("John Doe", "123 Main St");
person1.display();
// Update the address using the function
updateAddress(person1, "456 Cross St");
person1.display(); // The address should now be updated
return 0;
}

2. Assignment Operator and Classes:


In C++, the assignment operator (=) is used to assign the value of one object to another.
When dealing with objects, the assignment operator creates a reference to the existing object
rather than creating a new copy. This means that both variables will point to the same object
in memory, and any changes made through one reference will be reflected in the other.
Key Points:
❖ The assignment operator assigns a reference to the existing object.
❖ No new object is created; both variables refer to the same memory location.
❖ Any modifications made to the object through one reference will affect the object as seen through the other
reference.
❖ This can be useful for managing shared state but requires careful handling to avoid unintended side effects.

Example:
Let’s consider a Car class and demonstrate how the assignment operator works with objects.
#include <iostream>
using namespace std;
class Car {
public:
string make;
string model;
Car(string m, string mo) : make(m), model(mo) {}
void display() {
cout << "Car: " << make << " " << model << endl;
}
};

int main() {
// Create an instance of Car
Car my_car("Toyota", "Corolla");
my_car.display();
// Assign new_car to reference the same my_car object
Car &new_car = my_car;
new_car.display();
// Modify the new_car object
new_car.model = "Camry";
// Both references reflect the change
my_car.display();
new_car.display();
return 0;
}
Output: Car: Toyota Corolla; Car: Toyota Corolla; Car: Toyota Camry; Car: Toyota Camry
Explanation of the Example:
❖ Class Definition: The Car class has a constructor to initialize make and model
attributes. It has a display method to print these attributes.
❖ Object Creation: A Car object my_car is created with the make “Toyota” and model
“Corolla”. The display method is called to show the initial state of my_car.
❖ Assignment: The new_car reference is assigned to reference the same my_car object
using the assignment operator (=). The display method is called on new_car to show
that it references the same object.
❖ Modification: The model attribute of new_car is changed to “Camry”. Both my_car
and new_car reflect this change because they reference the same object.
By understanding how the assignment operator works with objects, you can effectively
manage object references and ensure that your programs behave as expected when
sharing and modifying objects.

3. Class Scope:
Class scope refers to the visibility and accessibility of class members (attributes and
methods) within a class. In C++, access levels control how these members can be accessed
from outside the class. The three primary access levels are public, private, and protected.
Key Points:
❖ Public Access: Members declared as public can be accessed from anywhere in the program. Public members
are accessible both inside and outside the class.
❖ Private Access: Members declared as private can only be accessed within the class itself. Private members
are not accessible from outside the class, ensuring encapsulation.
❖ Protected Access: Members declared as protected can be accessed within the class and by derived classes.
Protected members are not accessible from outside the class, but they can be accessed by subclasses.
Example:
Let’s consider a simple Car class to demonstrate these access levels.
#include <iostream>
using namespace std;
class Car {
public:
string make; // Public attribute
void display() { // Public method
cout << "Car make: " << make << endl;
cout << "Car model: " << model << endl;
}
private:
string model; // Private attribute
protected:
int year; // Protected attribute
};
int main() {
Car myCar;
myCar.make = "Toyota"; // Accessible
// myCar.model = "Corolla"; // Error: 'model' is private
// myCar.year = 2020; // Error: 'year' is protected
myCar.display(); // Accessible
return 0;
}
Explanation of the Example:
❖ Public Attribute and Method: The make attribute and display method are declared as
public, so they can be accessed from outside the class. In the main function, myCar.make
is assigned a value, and myCar.display() is called without any issues.
❖ Private Attribute: The model attribute is declared as private, so it cannot be accessed
directly from outside the class.Attempting to assign a value to myCar.model in the main
function results in a compilation error.
❖ Protected Attribute: The year attribute is declared as protected, so it cannot be accessed
directly from outside the class. Attempting to assign a value to myCar.year in the main
function results in a compilation error. However, year can be accessed by derived classes.
By understanding class scope and access levels, you can effectively control the visibility and
accessibility of class members, ensuring proper encapsulation and inheritance in your
programs.

4. Functions and Classes:


Functions vs. Methods in C++
Functions Outside Classes: Functions defined outside of classes are global functions. They can
be called from anywhere in the program, provided they are in scope. They do not operate on
class attributes unless explicitly passed as parameters.
Methods Inside Classes: Methods are functions defined within a class. They are specific to
instances of the class and can operate on the class’s attributes. Methods are called using an
instance of the class.
Key Points:
❖ Global Functions: Defined outside any class. Can be called without creating an instance of a class.
Example: int add(int a, int b) { return a + b; }
❖ Class Methods: Defined inside a class. Operate on class attributes and can modify the state of the object.
Example: void calculate_area() { area = length * width; }
Example: Let’s consider a Rectangle class with a method to calculate the area.
#include <iostream>
using namespace std;
// Global function
int add(int a, int b) {
return a + b;
}
class Rectangle {
public:
int length;
int width;
// Method to calculate area
int calculate_area() {
return length * width;
}
};
int main() {
// Using global function
cout << "Sum: " << add(5, 3) << endl;
// Using class method
Rectangle rect;
rect.length = 5;
rect.width = 3;
cout << "Area: " << rect.calculate_area() << endl;
return 0;
}
Output: Sum: 8 Area: 15
Explanation of the Example:
❖ Global Function: The add function is defined outside any class and can be called
directly in main.
❖ Class Method:The Rectangle class has a method calculate_area that operates on its
attributes length and width.
❖ An instance of Rectangle is created, and its attributes are set before calling
calculate_area.
By understanding the differences between global functions and class methods, you can
effectively manage how functions and methods interact with class attributes and instances
in your C++ programs.

5. Constructors and Default Parameters:


Constructors with Default Parameters: Constructors can have parameters with default
values.These parameters are optional when creating an object. If no arguments are provided,
the default values are used.
Key Points:
❖ Default Parameters: Parameters in a constructor can have default values.If arguments are not provided
during object creation, the default values are used.
❖ Optional Parameters: Parameters with default values are optional.This provides flexibility in object
creation.
Example: Let’s consider a Car class with a constructor that has default parameters.
#include <iostream>
using namespace std;
class Car {
public:
string make;
string model;

// Constructor with default parameters


Car(string m = "Unknown", string mo = "Unknown") {
make = m;
model = mo;
}

void display() {
cout << "Car make: " << make << ", model: " << model << endl;
}
};
int main() {
// Creating objects with and without parameters
Car car1; // Uses default parameters
Car car2("Toyota"); // Uses default for model
Car car3("Honda", "Civic"); // Provides both parameters
car1.display();
car2.display();
car3.display();
return 0;
}
Output:
Car make: Unknown, model: Unknown
Car make: Toyota, model: Unknown
Car make: Honda, model: Civic
Explanation of the Example:
❖ Constructor with Default Parameters: The Car class constructor has two parameters,
make and model, both with default values “Unknown”. If no arguments are provided,
the default values are used.
❖ Object Creation: car1 is created without any arguments, so it uses the default values.
car2 is created with only the make argument, so model uses the default value. car3 is
created with both make and model arguments, so no default values are used.
❖ Display Method: The display method prints the make and model of the car. The output
shows how the default parameters are used when arguments are not provided.
By using constructors with default parameters, you can provide flexibility in object creation,
allowing for both default and customized initialization of objects.

6. Destructors:
Destructors: Destructors are special member functions in a class that are called
automatically when an object is destroyed.Their primary purpose is to clean up resources
that the object may have acquired during its lifetime, such as memory, file handles, or
network connections.In C++, destructors have the same name as the class, prefixed with a
tilde (~).
Key Points:
❖ Automatic Invocation: Destructors are called automatically when an object goes out of scope or is explicitly
deleted. This ensures that resources are released properly without requiring explicit calls.
❖ Resource Management: Destructors are crucial for managing resources, especially in languages like C++
that do not have automatic garbage collection. They help prevent resource leaks by ensuring that resources
are freed when they are no longer needed.
❖ Syntax: Destructors do not take parameters and do not return values. Example syntax: ~ClassName() { /*
cleanup code */ }
Example: Let’s consider a simple Example class that demonstrates the use of a
destructor.
#include <iostream>
using namespace std;
class Example {
public:
// Constructor
Example() {
cout << "Constructor called." << endl;
}
// Destructor
~Example() {
cout << "Destructor called." << endl;
}
};
int main() {
{
Example ex;
// Object ex is created and constructor is called
} // Destructor is called automatically here when ex goes out of scope
return 0;
}

Output:
Constructor called.
Destructor called.
Explanation of the Example:
❖ Constructor: The Example class constructor prints a message when an object is created.
❖ Destructor: The Example class destructor prints a message when an object is destroyed.
❖ Automatic Invocation: In the main function, an Example object ex is created within a
block. When the block ends, ex goes out of scope, and the destructor is called
automatically, printing the message.
By using destructors, you can ensure that resources are properly managed and released,
preventing resource leaks and ensuring efficient use of system resources

7. Structs:
• Structs vs. Classes: Structs are similar to classes in that they can contain multiple data
members. However, structs are typically used for lightweight data structures that do not
require the full functionality of classes. Structs do not support inheritance or methods,
making them simpler and more efficient for certain use cases.
Key Points:
❖ Lightweight Data Structures: Structs are ideal for simple data structures that group related data together.
They are often used for small, immutable data types.
❖ No Inheritance or Methods: Structs do not support inheritance, meaning they cannot be extended or
derived from other structs or classes. They also do not support member functions (methods), focusing solely
on data storage.
❖ Default Public Access: In C++, members of a struct are public by default, unlike classes where members
are private by default.
Example: Let’s consider a simple Point struct that represents a point in 2D space with x and
y coordinates.
#include <iostream>
using namespace std;
struct Point {
int x;
int y;
};
int main() {
Point p1;
p1.x = 10;
p1.y = 20;
cout << "Point coordinates: (" << p1.x << ", " << p1.y << ")" << endl;
return 0;
}

Output: Point coordinates: (10, 20)


Explanation of the Example:
❖ Struct Definition: The Point struct is defined with two public data members: x and y.
❖ Object Creation: An instance of the Point struct, p1, is created. The x and y members of
p1 are assigned values.
❖ Accessing Members: The values of x and y are accessed directly and printed to the
console.
By using structs, you can create simple and efficient data structures that group related data
together without the overhead of classes. This is particularly useful for small, immutable
data types where the additional features of classes are not needed.

Viva Questions
1. What is a reference parameter and how does it differ from a value parameter?
2. How do reference parameters help in modifying the original data of an object?
3. Can you explain with an example how a class object is passed as a reference
parameter to a function?
4. What are the advantages of using reference parameters in functions?
5. How does passing an object by reference affect the performance of a program?
6. What happens if you try to modify a constant reference parameter?
7. What is the purpose of the assignment operator in C++?
8. How do you overload the assignment operator for a class?
9. What is the difference between shallow copy and deep copy in the context of the
assignment operator?
10. What issues can arise if the assignment operator is not properly overloaded?
11. How does the assignment operator differ from the copy constructor?
12. What is class scope and how does it affect the visibility of class members?
13. Explain the difference between public, private, and protected access specifiers.
14. How does class scope help in encapsulation?
15. Can you give an example of how a private member of a class is accessed?
16. What is the significance of the friend keyword in relation to class scope?
17. How does inheritance affect the scope of class members?
18. What is the difference between a global function and a class method?
19. How do methods within a class operate on class attributes?
20. How do you call a method of a class from an object?
21. How can you define a function outside the class definition?
22. What is a constructor and what is its primary purpose?
23. How do default parameters in constructors provide flexibility in object creation?
24. What is the difference between a default constructor and a parameterized constructor?
25. How does constructor overloading work in C++?
26. What happens if you do not define a constructor in a class?
27. What is a destructor and when is it called?
28. Can you explain the purpose of a destructor with an example?
29. How do destructors help in resource management?
30. What is the syntax for defining a destructor in C++?
31. What happens if a destructor is not defined in a class?
32. How do destructors differ from constructors?
33. What is a struct and how is it different from a class?
34. Can you provide an example of a simple struct in C++?
35. Why are structs typically used for lightweight data structures?
36. How do you access members of a struct?
37. What are the limitations of structs compared to classes?
38. Can structs contain methods in C++?

Theory Questions
1. Explain the concept of reference parameters and their advantages in C++ with an
example.
2. Discuss how passing objects by reference can improve the efficiency of a program.
3. Describe the process of overloading the assignment operator in C++. Provide an
example.
4. Explain the difference between shallow copy and deep copy in the context of the
assignment operator.
5. Define class scope and explain the significance of public, private, and protected access
specifiers with examples.
6. Discuss how class scope contributes to encapsulation in object-oriented programming.
7. Compare and contrast global functions and class methods in C++. Provide examples.
8. Explain how methods within a class operate on class attributes and modify the state
of an object.
9. What are constructors in C++? Explain the role of default parameters in constructors
with an example.
10. Discuss the differences between default constructors and parameterized constructors.
11. What is a destructor in C++? Explain its purpose and provide an example.
12. Discuss the importance of destructors in resource management and how they differ
from constructors.
13. Define structs in C++ and explain their typical use cases. Provide an example of a
simple struct.
14. Compare structs and classes in C++, highlighting their differences and limitations.
Session :3
Inheritance: Overriding Member Functions of the Base Class, Constructors of Derived and Base Classes, Header File of a Derived Class, Multiple Inclusions of a Header
File,
1. Overriding Member Functions of the Base Class
Overriding Member Functions:
o In C++, a derived class can override a member function of its base class.
o This means the derived class provides its own implementation of the function, which
replaces the base class’s version when called on an object of the derived class.
o To override a function, the derived class function must have the same signature as the
base class function.
Key Points:
❖ Function Signature: The overridden function in the derived class must have the same name and
parameters as the function in the base class.
❖ Polymorphism: Overriding is a key feature of polymorphism, allowing derived classes to provide specific
implementations of base class functions.
Example:
#include <iostream>
using namespace std;
class Base {
public:
void identify() const {
cout << "Base::identify()" << endl;
}
};
class Derived : public Base {
public:
void identify() const {
cout << "Derived::identify()" << endl;
}
};
int main() {
Base base;
Derived derived;
base.identify(); // Output: Base::identify()
derived.identify(); // Output: Derived::identify()
return 0;
}

2. Constructors of Derived and Base Classes


Constructors in Inheritance:
o When a derived class object is created, the base class constructor is called first,
followed by the derived class constructor.
o This ensures that the base part of the object is initialized before the derived part.
Key Points:
❖ Order of Construction: The base class constructor is called before the derived class constructor.
❖ Initialization: This order ensures that the base class part of the object is properly initialized before the
derived class part.
Example:
#include <iostream>
using namespace std;
class Base {
public:
Base() {
cout << "Base constructor called" << endl;
}
};
class Derived : public Base {
public:
Derived() {
cout << "Derived constructor called" << endl;
}
};
int main() {
Derived derived; // Output: Base constructor called
// Derived constructor called
return 0;
}
3. Header File of a Derived Class
Header Files:
o Header files in C++ contain declarations of classes, functions, and variables.
o For a derived class, the header file should include the header file of the base class to
ensure the base class is known to the compiler.
Example:
Base.h:
#ifndef BASE_H
#define BASE_H
class Base {
public:
void identify() const;
};
#endif // BASE_H
Derived.h:
#ifndef DERIVED_H
#define DERIVED_H
#include "Base.h"
class Derived : public Base {
public:
void identify() const;
};
#endif // DERIVED_H
Derived.cpp:
#include "Derived.h"
#include <iostream>
using namespace std;
void Derived::identify() const {
cout << "Derived::identify()" << endl;
}
Key Points:
❖ Include Base Class Header: The derived class header file must include the base class header file.
❖ Guard Against Multiple Inclusions: Use include guards (#ifndef, #define, #endif) to prevent multiple
inclusions of the same header file.

4. Multiple Inclusions of a Header File


Multiple Inclusions: Including the same header file multiple times can lead to redefinition
errors. To prevent this, use include guards or #pragma once.
Example:
Header Guards:
#ifndef MYCLASS_H
#define MYCLASS_H

class MyClass {
public:
void doSomething();
};

#endif // MYCLASS_H
Pragma Once:
#pragma once

class MyClass {
public:
void doSomething();
};
Key Points:
❖ Include Guards: Use #ifndef, #define, and #endif to prevent multiple inclusions.
❖ Pragma Once: #pragma once is a simpler, non-standard alternative to include guards that achieves the
same effect.
By understanding these principles, you can effectively manage inheritance, constructors, and
header files in C++ to create robust and maintainable code.
Viva Questions
o What is function overriding in C++ and how does it differ from function overloading?
o Can you explain with an example how a derived class can override a member function
of its base class?
o What is the significance of the virtual keyword in function overriding?
o How does the compiler determine which function to call when a function is
overridden?
o What happens if a derived class does not override a virtual function from the base
class?
o How can you call a base class function from a derived class if it has been overridden?
o Explain the order of constructor calls in a derived class and its base class.
o How do you pass arguments to a base class constructor from a derived class
constructor?
o What is the purpose of the initialization list in constructors, especially in the context
of inheritance?
o Can you provide an example where both base and derived class constructors are
called?
o What happens if a base class constructor requires parameters but the derived class
constructor does not provide them?
o How does the destructor call order differ from the constructor call order in
inheritance?
o Why is it important to include the base class header file in the derived class header
file?
o What are include guards and why are they used in header files?
o Can you explain the structure of a derived class header file with an example?
o How do you ensure that a header file is included only once in a program?
o What is the purpose of the #include directive in C++?
o How do you handle dependencies between multiple header files in a large project?
o What problems can arise from multiple inclusions of the same header file?
o How do include guards prevent multiple inclusions of a header file?
o Can you explain the syntax and usage of include guards with an example?
o What is #pragma once and how does it differ from traditional include guards?
o Are there any situations where #pragma once might not be supported?
o How do you decide whether to use include guards or #pragma once in your projects?

Theory Questions
o Define function overriding in C++ and discuss its importance in object-oriented
programming. Provide an example.
o Explain the role of the virtual keyword in function overriding and how it affects
polymorphism.
o Describe the order of constructor and destructor calls in a class hierarchy. Provide an
example to illustrate your explanation.
o Discuss the use of initialization lists in constructors, particularly in the context of
inheritance. Provide an example.
o Explain the structure of a derived class header file and the importance of including the
base class header file. Provide an example.
o Discuss the purpose and implementation of include guards in C++ header files.
Provide an example.
o What are the potential issues caused by multiple inclusions of the same header file?
How can these issues be prevented?
o Compare and contrast include guards and #pragma once as methods to prevent
multiple inclusions of header files. Provide examples of each.
Session :4
Protected Members of a Class, Inheritance as public, protected, or private, Polymorphism: Why Operator Overloading Is Needed, Syntax for Operator Functions,
1. Protected Members of a Class
Protected members in a class are similar to private members but with one key difference: they
can be accessed by derived classes. This access specifier is particularly useful in inheritance.
Key Points:
❖ Protected members are accessible within the class itself and by derived classes. They are not accessible from
outside the class.
Example:
#include <iostream>
using namespace std;
class Parent {
protected:
int id_protected;
};
class Child : public Parent {
public:
void setId(int id) {
id_protected = id; // Accessible here
}
void displayId() {
cout << "id_protected is: " << id_protected << endl;
}
};
int main() {
Child obj;
obj.setId(81);
obj.displayId(); // Output: id_protected is: 81
return 0;
}

2. Inheritance as Public, Protected, or Private


Inheritance in C++ can be specified as public, protected, or private, which determines the
accessibility of the base class members in the derived class.
Key Points:
❖ Public Inheritance: Public members of the base class remain public in the derived class. Protected members
of the base class remain protected in the derived class. Private members of the base class are not accessible
in the derived class.
❖ Protected Inheritance: Public and protected members of the base class become protected in the derived
class. Private members of the base class are not accessible in the derived class.
❖ Private Inheritance: Public and protected members of the base class become private in the derived class.
Private members of the base class are not accessible in the derived class.
Syntax:
class Base {
public:
int pub;
protected:
int prot;
private:
int priv;
};

class PublicDerived : public Base {


// pub is public
// prot is protected
// priv is not accessible
};

class ProtectedDerived : protected Base {


// pub is protected
// prot is protected
// priv is not accessible
};

class PrivateDerived : private Base {


// pub is private
// prot is private
// priv is not accessible
};
3. Polymorphism: Why Operator Overloading Is Needed
Polymorphism allows objects to be treated as instances of their base class rather than their
actual derived class. Operator overloading is a form of compile-time polymorphism.
Key Points:
❖ Definition: Operator overloading allows you to redefine the way operators work for user-defined types. It
provides a way to use operators with class objects in a manner similar to built-in types.
❖ Purpose: Enhances code readability and maintainability. Allows intuitive operations on user-defined types
(e.g., adding two complex numbers using the + operator).
Example:
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}

// Overloading the + operator


Complex operator+(const Complex& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}

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

int main() {
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // Using overloaded +
c3.print(); // Output: 12 + i9
return 0;
}

4. Syntax for Operator Functions


Operator functions are special member functions that define the behavior of operators for user-
defined types.
Key Points:
The syntax for defining an operator function is:
return_type operator op (argument_list) {
// function body
}
op is the operator being overloaded.
Example:
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
// Overloading the + operator
Complex operator+(const Complex& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() {
cout << real << " + i" << imag << endl;
}
};

int main() {
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // Using overloaded +
c3.print(); // Output: 12 + i9
return 0;
}

Viva Questions
1. What is the difference between protected and private members in a class?
2. Can protected members be accessed outside the class hierarchy?
3. How does public inheritance differ from protected and private inheritance in C++?
4. What happens to the private members of a base class when inherited?
5. Why is operator overloading necessary in C++?
6. Can all operators be overloaded in C++? Give an example of an operator that cannot be
overloaded.
7. What is the syntax for overloading the + operator in a class?
8. Why should the operator overloading function be defined as a member function or a
friend function?
9.
Theory Questions
1. Explain the significance of protected members in the context of inheritance.
2. Write a C++ program to demonstrate the use of protected members in a base and derived
class.
3. Explain the concept of protected inheritance with an example.
4. Describe the accessibility of base class members in private inheritance.
5. Explain with an example how operator overloading enhances code readability.
6. Discuss the advantages and disadvantages of operator overloading.
7. Write the syntax for overloading the << operator for a class and explain each part.
8. Explain the difference between member and non-member operator overloading functions
with examples.
Session :5
Overloading an Operator: Some Restrictions, The Pointer this, Friend Functions of Classes, Operator Functions as Member Functions and Non-member Functions,
Overloading Binary Operators, Overloading the Stream Insertion (<<) and Extraction (>>) Operators,

1. Overloading an Operator: Some Restrictions


Overloading an operator in C++ has some restrictions: you cannot change the precedence,
associativity, or the number of operands of operators. Certain operators, like ::, ., .*, ->*, and ?:,
cannot be overloaded. Additionally, overloaded operators must have at least one operand of a
user-defined type
Key Points:
❖ Operators that cannot be overloaded:
Scope resolution operator ::
Member access operator .
Member pointer access operators .* and ->*
Conditional operator ?:
❖ Rules:
You cannot change the precedence and associativity of operators.
You cannot change the arity (number of operands) of operators.
Overloaded operators must have at least one operand of a user-defined type.
Example:
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}

// Overloading the + operator


Complex operator+(const Complex& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}

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

int main() {
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // Using overloaded +
c3.print(); // Output: 12 + i9
return 0;
}

2. The Pointer this


This pointer in C++ is an implicit pointer available within all non-static member functions,
pointing to the object for which the member function is called. It is used to access the object’s
members and can be used to return the object itself from a member function. This pointer helps
in distinguishing between member variables and parameters with the same name.
Key Points:
❖ Definition: this is a pointer to the object for which a member function is called. It is implicitly passed to all
non-static member functions.
❖ Usage: To access members of the object within member functions. To return the object itself from a member
function.
Example:
class Test {
private:
int x;
public:
void setX(int x) {
this->x = x; // Using 'this' to refer to the object's member
}

void print() {
cout << "x = " << x << endl;
}
};
int main() {
Test obj;
obj.setX(20);
obj.print(); // Output: x = 20
return 0;
}

3. Friend Functions of Classes


Key Points:
❖ Definition: Friend functions can access private and protected members of a class. They are not member
functions but are declared inside the class with the friend keyword.
❖ Usage: To allow external functions to access private data. To operate on objects of different classes.
Example:

private:
int meter;
public:
Distance() : meter(0) {}
// Friend function declaration
friend int addFive(Distance);
};

// Friend function definition


int addFive(Distance d) {
d.meter += 5;
return d.meter;
}
int main() {
Distance D;
cout << "Distance: " << addFive(D) << endl; // Output: Distance: 5
return 0;
}

4. Operator Functions as Member Functions and Non-member Functions


Key Points:
❖ Member Functions: The left operand must be an object of the class.The function is a member of the class.
❖ Non-member Functions: Typically implemented as friend functions.Can access private and protected
members if declared as friends.
Example:
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
// Member function for overloading +
Complex operator+(const Complex& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
// Friend function for overloading +
friend Complex operator+(const Complex& obj1, const Complex& obj2) {
Complex res;
res.real = obj1.real + obj2.real;
res.imag = obj1.imag + obj2.imag;
return res;
}

void print() {
cout << real << " + i" << imag << endl;
}
};
int main() {
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // Using overloaded + (member function)
c3.print(); // Output: 12 + i9
return 0;
}
5. Overloading Binary Operators
Key Points:
❖ Definition: Binary operators take two operands. Can be overloaded as member or non-member functions.
❖ Syntax: Member function: Return Type operator op (const Type& operand); Non-member function: Return
Type operator op (const Type& lhs, const Type& rhs);
Example:
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
// Overloading the + operator
Complex operator+(const Complex& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() {
cout << real << " + i" << imag << endl;
}
};
int main() {
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // Using overloaded +
c3.print(); // Output: 12 + i9
return 0;
}

6. Overloading the Stream Insertion (<<) and Extraction (>>) Operators


Key Points:
❖ Stream Insertion (<<): Used to output the contents of an object. Must be a non-member function.
❖ Stream Extraction (>>): Used to input the contents of an object. Must be a non-member function.
Example:
#include <iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
// Overloading the << operator
friend ostream& operator<<(ostream& out, const Complex& c) {
out << c.real << " + i" << c.imag;
return out;
}
// Overloading the >> operator
friend istream& operator>>(istream& in, Complex& c) {
in >> c.real >> c.imag;
return in;
}
};
int main() {
Complex c1;
cout << "Enter a complex number (real and imaginary parts): ";
cin >> c1; // Using overloaded >>
cout << "The complex number is: " << c1 << endl; // Using overloaded <<
return 0;
}
Class Definition
This code defines a class named Complex which represents complex numbers. A complex number has a real
part and an imaginary part.
Constructor
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
This is a constructor for the Complex class. It takes two optional parameters r and i which default to 0. The
constructor initializes the member variables real and imag with the values of r and i respectively.
Overloading the << Operator
friend ostream& operator<<(ostream& out, const Complex& c) {
out << c.real << " + i" << c.imag;
return out;
}
This function overloads the << operator to allow easy output of Complex objects. It is a friend function,
meaning it can access private and protected members of the Complex class. The function takes an ostream
object out and a Complex object c. It outputs the real and imag parts of the complex number in the format
real +i imag. Finally, it returns the ostream object to allow chaining of output operations.
Overloading the >> Operator
friend istream& operator>>(istream& in, Complex& c) {
in >> c.real >> c.imag;
return in;
}
This function overloads the >> operator to allow easy input of Complex objects. It is also a friend
function.The function takes an istream object in and a Complex object c. It reads values into the real and
imag parts of the complex number from the input stream. Finally, it returns the istream object to allow
chaining of input operations.
Session :6
Operator Overloading: Member Versus Non-member, Programming Example: Complex Numbers, Function Overloading,
Templates: Function Templates, Class Templates, Header File and Implementation File of a Class Template
1. Operator Overloading: Member Versus Non-member
Operator overloading allows C++ operators to be redefined and used with user-defined data
types. It provides a way to perform operations on objects in a natural and intuitive manner.
o Member Function: When the left operand of the operator is an object of the class, the
operator overloading function should be a member function.
o Non-member Function: When the left operand is not an object of the class, the
operator overloading function should be a non-member function. It can be a friend
function if it needs access to private or protected members.
o Key Points
o Member functions are used when the operator modifies the left-hand operand.
o Non-member functions are used when the operator does not modify the left-hand
operand or when the left-hand operand is not an object of the class.
o Friend functions can access private and protected members of the class.
Example:

#include <iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
// Member function for overloading +
Complex operator+(const Complex& obj) {
return Complex(real + obj.real, imag + obj.imag);
}
// Friend function for overloading <<
friend ostream& operator<<(ostream& out, const Complex& c) {
out << c.real << " + i" << c.imag;
return out;
}
};
int main() {
Complex c1(3, 4), c2(1, 2);
Complex c3 = c1 + c2;
cout << "Sum: " << c3 << endl;
return 0;
}

2. Programming Example: Complex Numbers


Complex numbers have a real part and an imaginary part. In C++, we can create a class to
represent complex numbers and overload operators to perform arithmetic operations on
them.
Key Points
❖ Use constructors to initialize complex numbers.
❖ Overload arithmetic operators to perform operations like addition, subtraction, etc.
❖ Overload stream insertion and extraction operators for easy input and output.
Example:
#include <iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
// Overloading + operator
Complex operator+(const Complex& obj) {
return Complex(real + obj.real, imag + obj.imag);
}
// Overloading << operator
friend ostream& operator<<(ostream& out, const Complex& c) {
out << c.real << " + i" << c.imag;
return out;
}
// Overloading >> operator
friend istream& operator>>(istream& in, Complex& c) {
in >> c.real >> c.imag;
return in;
}
};
int main() {
Complex c1, c2;
cout << "Enter first complex number: ";
cin >> c1;
cout << "Enter second complex number: ";
cin >> c2;
Complex c3 = c1 + c2;
cout << "Sum: " << c3 << endl;
return 0;
}

3. Function Overloading
Function overloading allows multiple functions with the same name to exist, provided they
have different parameter lists. It is a form of compile-time polymorphism.
Key Points
❖ Functions must differ in the number or type of their parameters.
❖ Return type alone is not sufficient to distinguish overloaded functions.
❖ Improves code readability and reusability.
Example:
#include <iostream>
using namespace std;
// Function to add two integers
int add(int a, int b) {
return a + b;
}
// Function to add two doubles
double add(double a, double b) {
return a + b;
}
int main() {
cout << "Sum of integers: " << add(3, 4) << endl;
cout << "Sum of doubles: " << add(3.5, 4.5) << endl;
return 0;
}

4. Templates: Function Templates


Function templates allow functions to operate with generic types. This enables a function to
work with different data types without being rewritten for each one.
Key Points
❖ Defined using the template keyword.
❖ Can be used to create functions that work with any data type.
❖ Improves code reusability and maintainability.
Example:
#include <iostream>
using namespace std;
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
cout << "Sum of integers: " << add(3, 4) << endl;
cout << "Sum of doubles: " << add(3.5, 4.5) << endl;
return 0;
}

5. Templates: Class Templates


Class templates allow classes to operate with generic types. This enables a class to work with
different data types without being rewritten for each one.
Key Points
❖ Defined using the template keyword.
❖ Can be used to create classes that work with any data type.
❖ Improves code reusability and maintainability.
Example:
#include <iostream>
using namespace std;
template <typename T>
class Array {
private:
T* arr;
int size;
public:
Array(int s) : size(s) {
arr = new T[size];
}
T& operator {
return arr[index];
}
~Array() {
delete[] arr;
}
};
int main() {
Array<int> intArray(5);
for (int i = 0; i < 5; ++i) {
intArray[i] = i * 2;
}
for (int i = 0; i < 5; ++i) {
cout << intArray[i] << " ";
}
cout << endl;
return 0;
}

6. Templates: Header File and Implementation File of a Class Template


Class templates can be defined in header files and implemented in separate implementation
files. This helps in organizing code and improving readability.
Key Points
❖ Template class definitions are usually placed in header files.
❖ Template class implementations can be placed in separate implementation files.
❖ The implementation file is included in the header file to avoid linking errors.
Example:
Header File (Array.h)
#ifndef ARRAY_H
#define ARRAY_H

template <typename T>


class Array {
private:
T* arr;
int size;
public:
Array(int s);
T& operator;
~Array();
};

#include "Array.cpp"
#endif
Implementation File (Array.cpp)
#include "Array.h"
#include <iostream>
using namespace std;

template <typename T>


Array<T>::Array(int s) : size(s) {
arr = new T[size];
}

template <typename T>


T& Array<T>::operator {
return arr[index];
}

template <typename T>


Array<T>::~Array() {
delete[] arr;
}
Viva Questions
1. What is operator overloading and why is it used in C++?
2. Explain the difference between member and non-member operator overloading functions.
3. How do you overload the + operator for a class representing complex numbers?
4. Explain the purpose of friend functions in operator overloading.
5. What is function overloading and how does it differ from function overriding?
6. Can you overload functions based on their return type alone? Why or why not?
7. What is a function template and how is it different from a regular function?
8. Explain the syntax of defining a function template in C++.
9. Why do we include the implementation file in the header file for class templates?
10. Explain the common issues faced when separating template class definitions and implementations.
11. What is a class template and how is it different from a regular class?
12. Explain the syntax of defining a class template in C++.

Theory Questions
1. Describe the advantages and disadvantages of using friend functions for operator overloading.
2. Write a C++ program to overload the * operator for a class representing complex numbers.
3. Write a C++ program to overload the - operator for a class representing complex numbers.
4. Discuss the importance of overloading the stream insertion and extraction operators for complex numbers.
5. Write a C++ program to overload the max function for different data types.
6. Explain the rules and restrictions for function overloading in C++.
7. Write a function template to find the maximum of two values.
8. Discuss the advantages and disadvantages of using function templates.
9. Write a class template for a stack data structure.
10. Discuss the benefits of using class templates in C++.
11. Write a header file and an implementation file for a class template representing a dynamic array.
12. Discuss the advantages and disadvantages of separating template class definitions and implementations.

Session :7
give me a detailed notes on each of the following topics in c++ with explanation, key points and a simple example :
give me 2 viva questions and 2 theory questions for exam on each of the following topics answers not required only the questions:
Pointer Data Type and Pointer Variables: Declaring Pointer Variables, Address of Operator (&), Dereferencing Operator (*), Pointers and Classes, Initializing Pointer
Variables, Dynamic Variables, Operator new, Operator delete, Operations on Pointer Variables, Dynamic Arrays, Array

1. Declaring Pointer Variables


Explanation: A pointer is a variable that stores the memory address of another variable.
The syntax for declaring a pointer is:
data_type *pointer_name;
Key Point:
❖ The * operator is used to declare a pointer.
The data type of the pointer must match the data type of the variable it points to.
Example:
int *ptr;

2. Address of Operator (&)


Explanation: The address-of operator (&) is used to obtain the memory address of a
variable.
Key Point:
❖ It returns the address of its operand.
Example:
int var = 10;
int *ptr = &var;

3. Dereferencing Operator (*)


Explanation: The dereferencing operator (*) is used to access the value stored at the
address held by a pointer.
Key Point:
❖ It allows access to the value at the pointer’s address.
Example:
int var = 10;
int *ptr = &var;
int value = *ptr; // value is 10

4. Pointers and Classes


Pointers can be used to access members of a class.
Key Point:
❖ Use the arrow operator (->) to access class members via a pointer.
Example:
class MyClass {
public:
int data;
};

MyClass obj;
MyClass *ptr = &obj;
ptr->data = 5;

5. Initializing Pointer Variables


Explanation: Pointers should be initialized to nullptr or a valid address before use.
Key Point:
❖ Uninitialized pointers can lead to undefined behavior.
Example:
int *ptr = nullptr;

6. Dynamic Variables
Explanation: Dynamic variables are allocated memory at runtime using the new operator.
Key Point:
❖ Use new to allocate memory and delete to deallocate.
Example:
int *ptr = new int;
*ptr = 10;
delete ptr;

7. Operator new
Explanation: The new operator allocates memory for a variable at runtime.
Key Point:
❖ Returns a pointer to the allocated memory.
Example:
int *ptr = new int;

8. Operator delete
The delete operator deallocates memory that was previously allocated with new.
Key Point:
❖ Prevents memory leaks.
Example:
delete ptr;

9. Operations on Pointer Variables


Pointers support various operations like assignment, comparison, and arithmetic.
Key Point:
❖ Pointer arithmetic is based on the size of the data type.
Example:
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;
ptr++; // Points to the next element in the array

10. Array and Dynamic Arrays


An array is a collection of elements of the same type stored in contiguous memory
locations. Dynamic arrays are arrays whose size is determined at runtime.
Key Points:
❖ Arrays can be accessed using pointers.
❖ Use new to allocate and delete[] to deallocate.
Example:
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;
Example:
int *arr = new int[5];
delete[] arr;

Viva Questions
What is a pointer and how is it declared in C++?
Explain the difference between the address-of operator (&) and the dereferencing operator

Theory Questions
Describe the process of dynamic memory allocation in C++ using the new and delete
operators.
How can pointers be used to access members of a class in C++?
Feel free to ask if you need further details or examples on any specific topic!
Session :8
give me a detailed notes on each of the following topics in c++ with explanation, key points and a simple example :
give me 2 viva questions and 2 theory questions for exam on each of the following topics answers not required only the questions:
Name: A Constant Pointer, Functions and Pointers, Pointers and Function Return Values, Dynamic Two-Dimensional Arrays,
1. Constant Pointer
A constant pointer is a pointer whose address cannot be changed after initialization.
However, the value at the address it points to can be modified.
Key Points:
❖ Declared using the const keyword.
❖ Must be initialized at the time of declaration.
❖ The pointer itself cannot point to another address after initialization.
Example:
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
int* const ptr = &a; // Constant pointer to 'a'

*ptr = 15; // Allowed: modifying the value at the address


// ptr = &b; // Error: cannot change the address the pointer points to

cout << "Value of a: " << *ptr << endl; // Output: 15


return 0;
}

2. Functions and Pointers


Explanation:
Pointers can be used to pass variables to functions by reference, allowing the function to
modify the original variable.
Key Points:
❖ Functions can accept pointers as arguments.
❖ Useful for modifying the original data.
❖ Can be used to return multiple values from a function.
Example:
#include <iostream>
using namespace std;

void increment(int* ptr) {


(*ptr)++;
}

int main() {
int num = 10;
increment(&num);
cout << "Value of num: " << num << endl; // Output: 11
return 0;
}

3. Pointers and Function Return Values


Functions can return pointers, allowing dynamic memory allocation and manipulation of
data outside the function scope.
Key Points:
❖ Functions can return pointers to dynamically allocated memory.
❖ Ensure the memory is properly managed to avoid memory leaks.
Example:
#include <iostream>
using namespace std;

int* createArray(int size) {


int* arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = i + 1;
}
return arr;
}

int main() {
int* myArray = createArray(5);
for (int i = 0; i < 5; i++) {
cout << myArray[i] << " "; // Output: 1 2 3 4 5
}
delete[] myArray; // Free the allocated memory
return 0;
}

4. Dynamic Two-Dimensional Arrays


Explanation:
Dynamic two-dimensional arrays are arrays whose size can be determined at runtime,
allowing for flexible memory usage.
Key Points:
❖ Use pointers to pointers for dynamic 2D arrays.
❖ Allocate memory using nested loops.
Example:
#include <iostream>
using namespace std;
int main() {
int rows = 3, cols = 4;
int** arr = new int*[rows];
for (int i = 0; i < rows; i++) {
arr[i] = new int[cols];
}

// Initialize the array


for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i][j] = i * cols + j + 1;
}
}

// Print the array


for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}

// Deallocate memory
for (int i = 0; i < rows; i++) {
delete[] arr[i];
}
delete[] arr;

return 0;
}

Viva Questions:
What is a constant pointer in C++?
Can the address stored in a constant pointer be changed after initialization?
How do you pass a pointer to a function in C++?
What are the advantages of using pointers in function arguments?
Can a function return a pointer in C++?
What precautions should be taken when returning pointers from functions?
How do you create a dynamic two-dimensional array in C++?
What are the advantages of using dynamic arrays over static arrays?

Theory Questions:
Explain the difference between a constant pointer and a pointer to a constant.
Write a C++ program to demonstrate the use of a constant pointer.
Write a function that swaps two integers using pointers.
Explain how pointers can be used to return multiple values from a function.
Write a function that returns a pointer to a dynamically allocated array.
Explain the concept of memory leaks and how to prevent them when using pointers.
Write a C++ program to create and initialize a dynamic two-dimensional array.
Explain the process of deallocating memory for a dynamic two-dimensional array.
Session :9
give me a detailed notes on each of the following topics in c++ with explanation, key points and a simple example :
give me 2 viva questions and 2 theory questions for exam on each of the following topics answers not required only the questions:
Shallow Vs. Deep Copy and Pointers, Destructor, Classes &Pointers Assignment Operator, Copy Constructor,
1. Shallow vs. Deep Copy and Pointers
• Shallow Copy: Copies all member values from one object to another. If the object contains
pointers, only the pointer addresses are copied, not the actual data they point to.
• Deep Copy: Copies all member values and the data pointed to by any pointers. This ensures
that the new object is completely independent of the original.
Key Points:
❖ Shallow copy can lead to issues like dangling pointers and double deletion.
❖ Deep copy requires a user-defined copy constructor and assignment operator.
Example:
#include <iostream>
using namespace std;

class Box {
private:
int* ptr;
public:
Box(int val) {
ptr = new int;
*ptr = val;
}
// Copy Constructor for Deep Copy
Box(const Box& b) {
ptr = new int;
*ptr = *(b.ptr);
}
void setValue(int val) {
*ptr = val;
}
void display() {
cout << "Value: " << *ptr << endl;
}
~Box() {
delete ptr;
}
};

int main() {
Box box1(10);
Box box2 = box1; // Deep copy
box2.setValue(20);
box1.display(); // Output: Value: 10
box2.display(); // Output: Value: 20
return 0;
}

2. Destructor
A destructor is a special member function that is executed when an object goes out of scope
or is explicitly deleted. It is used to release resources allocated to the object.
Key Points:
❖ Declared with a tilde (~) followed by the class name.
❖ No return type and no parameters.
❖ Automatically called when an object is destroyed.
Example:
#include <iostream>
using namespace std;

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

int main() {
Demo obj;
return 0;
}

3. Classes & Pointers Assignment Operator


The assignment operator (=) is used to copy values from one object to another of the same
class. When dealing with pointers, a deep copy is often necessary to avoid issues.
Key Points:
❖ Default assignment operator performs a shallow copy.
❖ Custom assignment operator can be defined to perform a deep copy.
Example:
#include <iostream>
using namespace std;

class Box {
private:
int* ptr;
public:
Box(int val) {
ptr = new int;
*ptr = val;
}
// Assignment Operator for Deep Copy
Box& operator=(const Box& b) {
if (this != &b) {
delete ptr;
ptr = new int;
*ptr = *(b.ptr);
}
return *this;
}
void display() {
cout << "Value: " << *ptr << endl;
}
~Box() {
delete ptr;
}
};

int main() {
Box box1(10);
Box box2(20);
box2 = box1; // Deep copy
box1.display(); // Output: Value: 10
box2.display(); // Output: Value: 10
return 0;
}

4. Copy Constructor
A copy constructor is a special constructor used to create a new object as a copy of an
existing object. It is essential for deep copying.
Key Points:
❖ Takes a reference to an object of the same class as a parameter.
❖ Used to initialize an object from another object.
Example:
#include <iostream>
using namespace std;

class Box {
private:
int* ptr;
public:
Box(int val) {
ptr = new int;
*ptr = val;
}
// Copy Constructor for Deep Copy
Box(const Box& b) {
ptr = new int;
*ptr = *(b.ptr);
}
void display() {
cout << "Value: " << *ptr << endl;
}
~Box() {
delete ptr;
}
};

int main() {
Box box1(10);
Box box2 = box1; // Deep copy using copy constructor
box1.display(); // Output: Value: 10
box2.display(); // Output: Value: 10
return 0;
}

Viva Questions:
1. What is the difference between shallow copy and deep copy?
2. Why is a deep copy necessary when dealing with pointers?
3. What is the purpose of the assignment operator in C++?
4. How can you ensure a deep copy using the assignment operator?
5. What is a destructor in C++?
6. When is a destructor called
7. What is a copy constructor in C++?
8. When is a copy constructor called?

Theory Questions:
1. Explain the potential issues with shallow copying in C++.
2. Write a C++ program to demonstrate deep copying.
3. Explain the difference between the default and custom assignment operators.
4. Write a C++ program to demonstrate the use of a custom assignment operator.
5. Explain the role of a destructor in resource management.
6. Write a C++ program to demonstrate the use of a destructor.
7. Explain the importance of a copy constructor in C++.
8. Write a C++ program to demonstrate the use of a copy constructor.
Session :10
give me a detailed notes on each of the following topics in c++ with explanation, key points and a simple example :
give me 2 viva questions and 2 theory questions for exam on each of the following topics answers not required only the questions:
Inheritance Pointers &Virtual functions: Classes and Virtual Destructors 168, Array Based Lists:
Copy Constructor, Overloading the Assignment Operator, Search, Insert, Remove, Time Complexity of List Operations

1. Inheritance, Pointers & Virtual Functions: Classes and Virtual Destructors


Inheritance allows a class (derived class) to inherit properties and behaviors from another
class (base class). Pointers can be used to reference objects dynamically. Virtual functions
enable polymorphism, allowing derived classes to override base class methods. Virtual
destructors ensure that destructors of derived classes are called correctly when an object is
deleted through a base class pointer.
Key Points
❖ Inheritance: Enables code reusability and hierarchical classification.
❖ Pointers: Used for dynamic memory allocation and object referencing.
❖ Virtual Functions: Allow derived classes to override base class methods.
❖ Virtual Destructors: Ensure proper cleanup of derived class objects.
Example
#include <iostream>
using namespace std;

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

class Derived : public Base {


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

int main() {
Base* b = new Derived();
b->show();
delete b;
return 0;
}
When Base* b = new Derived(); is executed, the Base class constructor is called first,
printing “Base Constructor”. Next, the Derived class constructor is called, printing “Derived
Constructor”. The show function is called on the Base pointer b. Since show is a virtual
function, the Derived class’s show method is called, printing “Derived show”. When delete b;
is executed, the Derived class destructor is called first, printing “Derived Destructor”,
followed by the Base class destructor, printing “Base Destructor”.
2. Array-Based Lists
Array-based lists use arrays to store elements. They provide efficient access and
modification but have fixed size, requiring resizing for dynamic operations.
Key Points
❖ Copy Constructor: Creates a new object as a copy of an existing object.
❖ Overloading the Assignment Operator: Allows assigning one object to another.
❖ Search: Finding an element in the list.
❖ Insert: Adding an element to the list.
❖ Remove: Deleting an element from the list.
❖ Time Complexity: Efficiency of list operations.

Example
#include <iostream>
using namespace std;
class ArrayList {
private:
int* arr;
int size;
int capacity;

public:
ArrayList(int cap) : size(0), capacity(cap) {
arr = new int[capacity];
}

~ArrayList() {
delete[] arr;
}

void insert(int value) {


if (size < capacity) {
arr[size++] = value;
} else {
cout << "List is full\n";
}
}

void remove(int index) {


if (index >= 0 && index < size) {
for (int i = index; i < size - 1; ++i) {
arr[i] = arr[i + 1];
}
--size;
} else {
cout << "Invalid index\n";
}
}

int search(int value) {


for (int i = 0; i < size; ++i) {
if (arr[i] == value) {
return i;
}
}
return -1;
}

void display() {
for (int i = 0; i < size; ++i) {
cout << arr[i] << " ";
}
cout << endl;
}
};

int main() {
ArrayList list(10);
list.insert(5);
list.insert(10);
list.insert(15);
list.display();
list.remove(1);
list.display();
cout << "Index of 15: " << list.search(15) << endl;
return 0;
}
In the above code The insert method adds elements to the list. If the list is not full, the
element is added, and the size is incremented. The remove method deletes an element at a
specified index. It shifts all subsequent elements one position to the left and decrements the
size. The search method looks for an element in the list. It returns the index of the element if
found, otherwise returns -1 and the display method prints all elements in the list.

3. Time Complexity of Array-Based List Operations


Understanding the time complexity of various operations in an array-based list is crucial for
optimizing performance and making informed decisions about data structure usage. Here,
we’ll analyze the time complexity of the insert, remove, and search operations in the
ArrayList class.

1. Insert Operation Time Complexity:


• Best Case (O(1)): When the array has space available, inserting an element is a constant time
operation because it simply involves placing the element at the next available index.
• Worst Case (O(n)): If the array is full and needs resizing, the time complexity becomes O(n)
because it involves creating a new array and copying all elements from the old array to the new
one.
Explanation: Inserting an element when there is space in the array is very efficient, taking
constant time. However, if the array is full, resizing is required, which involves allocating a
new array and copying all existing elements, leading to a linear time complexity.

2. Remove Operation Time Complexity:


• Best Case (O(1)): Removing the last element is a constant time operation because it only involves
decrementing the size.
• Worst Case (O(n)): Removing an element from the beginning or middle of the array requires
shifting all subsequent elements one position to the left, resulting in a linear time complexity.
Explanation: Removing the last element is efficient as it does not require shifting elements.
Removing an element from any other position requires shifting elements, which takes linear
time.
3. Search Operation Time Complexity:
• Best Case (O(1)): If the element to be searched is at the first position, the search operation takes
constant time.
• Worst Case (O(n)): If the element is not present or is at the last position, the search operation
requires checking all elements, resulting in a linear time complexity.
Explanation: Searching for an element involves iterating through the array until the
element is found or the end of the array is reached. In the worst case, the search operation
requires checking each element, leading to linear time complexity.

Viva Questions
What is the purpose of a virtual destructor in C++?
How does polymorphism work in C++?
What is the difference between a copy constructor and an assignment operator?
How do you handle dynamic resizing in an array-based list?

Theory Questions
Explain the concept of inheritance and its types in C++.
Describe the role of virtual functions in achieving runtime polymorphism.
Explain the time complexity of search, insert, and remove operations in an array-based list.
Describe the process of overloading the assignment operator in C++.

You might also like