BSc CSIT Second Semester OOP: Important Chapter-Wise Questions
Welcome, Second Semester BSc CSIT students! Preparing for your OOP exam requires understanding key concepts and practicing relevant problems. To help you focus your studies, we've compiled a list of important questions based on past papers and the official syllabus, categorized chapter-wise. You can use this guide to test your knowledge and prepare effectively for your examinations.
📘 BSc CSIT – Object-Oriented Programming (OOP) Chapter-wise Past Questions
This post contains the past 5 years' questions of the BSc CSIT OOP subject, organized chapter-wise according to the official syllabus.
📘 Unit 1: Introduction to Object-Oriented Programming
1. Define object. What are the benefits of object-oriented programming Language?
Solution:
Object:
An object can be defined as a data field that has unique attributes and behaviors.
The benefits of object-oriented programming Language are
Modularity: Code is divided into objects, making it easier to manage and understand.
Reusability: Classes and objects can be reused across programs using inheritance.
Scalability: OOP makes it easy to update or scale applications by adding new classes and features.
Maintainability: Since the code is modular, it is easier to fix bugs or make changes without affecting the entire system.
Data Hiding (Encapsulation): Internal details of objects are hidden from the outside world, exposing only the necessary parts.
Real-world Modeling: OOP is based on real-world objects, making programs more understandable and relatable.
Improved Productivity: Reusability and modularity speed up the development process.
Inheritance: It is a feature or a process in which new classes are created from an existing class.
Polymorphism: Polymorphism means "many forms." In OOP, it allows one function, method, or operator to behave differently based on the object it is acting upon.
Encapsulation: It is a way of hiding data in a single entity or unit and a way of protecting information from the outside world.
2. Describe the characteristics of an object-oriented programming language.
Solution:
The characteristics of an object-oriented programming language are
Object: An object can be defined as a data field that has unique attributes and behaviors.
Class: A class represents a set of related objects.
Abstraction: It is a way of hiding unnecessary information.
Inheritance: It is a feature or a process in which new classes are created from an existing class.
Polymorphism: Polymorphism means "many forms." In OOP, it allows one function, method, or operator to behave differently based on the object it is acting upon.
Encapsulation: It is a way of hiding data in a single entity or unit and a way of protecting information from the outside world.
3. How does object-oriented programming differ from object-based programming? Discuss the benefits of OOP.
Solution:
The benefits of object-oriented programming Language are
Modularity: Code is divided into objects, making it easier to manage and understand.
Reusability: Classes and objects can be reused across programs using inheritance.
Scalability: OOP makes it easy to update or scale applications by adding new classes and features.
Maintainability: Since the code is modular, it is easier to fix bugs or make changes without affecting the entire system.
Data Hiding (Encapsulation): Internal details of objects are hidden from the outside world, exposing only the necessary parts.
Real-world Modeling: OOP is based on real-world objects, making programs more understandable and relatable.
Improved Productivity: Reusability and modularity speed up the development process.
Inheritance: It is a feature or a process in which new classes are created from an existing class.
Polymorphism: Polymorphism means "many forms." In OOP, it allows one function, method, or operator to behave differently based on the object it is acting upon.
Encapsulation: It is a way of hiding data in a single entity or unit and a way of protecting information from the outside world.
4. What is structured programming? Discuss characteristics and problems associated with structured programming.
Solution:
Structured programming is a programming pattern that gives special importance to breaking down a program into smaller, manageable, and logical units or modules.
Characteristics of Structured Programming:
-Top-down design: The program is broken into small, manageable modules or functions.
-Use of control structures only: Focuses on if-else, loops, and function calls instead of goto.
-Modular approach: Code is divided into functions or procedures for better organization.
-Improved readability and maintainability
-Single entry and single exit in each block of code
Problems with Structured Programming:
-No Object Reusability: Lacks inheritance and object reuse.
-Not suitable for large applications: Managing thousands of functions without classes/objects can be messy.
-Less real-world modeling: Hard to represent real-world entities compared to OOP.
-Poor scalability: Difficult to extend and modify as complexity grows.
Some important topics:
📘 Unit 2: Basics of C++ Programming
1. Explain the significance of type conversion. How do we achieve dynamic memory allocation in C++? Explain with an example.
Solution:
Type conversion is the process of changing one data type to another, such as converting an int to a float or vice versa.
Importance / Significance:
- Ensures compatibility between different data types during operations.
- Prevents data loss or errors during calculations.
- Helps in type-safe operations in mixed expressions.
- Improves code readability and maintainability by making type intentions clear.
Types of Type Conversion in C++:
a) Implicit Conversion: Done automatically by the compiler. (e.g., int to float)
b) Explicit Conversion (Casting): Done manually by the programmer using cast syntax. (e.g., (float)num)
Dynamic Memory Allocation: The process of allocating memory during runtime using pointers.
Keyword use in Dynamic Memory Allocation.
new: Allocates memory on the heap
delete: Deallocates memory from the heap
Example :
// new and delete
#include<iostream>
using namespace std;
int main()
{
int size;
cout<<"enter the size of array:\n";
cin>>size;
int *ptr=new int[size];
for(int i=0;i<size;i++)
{
cout<<"Enter the "<<i+1<<" data of the array:\t";
cin>>ptr[i];
}
cout<<"Data you enter are:\n"<<endl;
for(int i=0;i<size;i++)
{
cout<<ptr[i]<<"\t";
}
delete [] ptr;
}
Why Use Dynamic Memory?
-When the size of the data is unknown at compile time
-To create flexible data structures like linked lists, trees, etc.
-More efficient memory use in large program
2. What is meant by type conversion? Define two ways of converting one user-defined data type (object) to another.
Type conversion is the process of changing one data type to another, such as when operations involve different data types or when custom objects (user-defined types) need to interact.
Two Ways of Converting One User-Defined Data Type (Object) to Another in C++:
1. Conversion through Constructor (Single-Argument Constructor):
This allows a class to accept an object of another class and convert it.
🔹 Use Case: Target class has a constructor that accepts the source class object.
// Example:conversion of datatype using constructor
#include<iostream>
using namespace std;
class B;
class A
{
public:
int x;
A(int value)
{
x=value;
}
};
class B
{
public:
int y;
B( A obj)
{
y=obj.x;
}
void show()
{
cout<<"The value of B is:"<<y<<endl;
}
};
int main()
{
A a1(5);
B b1=a1;
b1.show();
}
2. Conversion through Operator Overloading (Type Conversion Operator):
We define a type-cast operator inside the class to convert one object type to another.
🔹 Use Case: Source class defines a conversion function to return the target type.
// data conversion using operator overloading
#include<iostream>
using namespace std;
class B;
class A
{ public:
int x;
A(int value)
{
x=value;
}
operator B();
};
class B
{ public:
int y;
void show()
{
cout<<"The value of B:"<<y<<endl;
}
};
A::operator B()
{
B temp;
temp.y=x;
return temp;
}
int main()
{
A a1(5);
B b2=a1;
b2.show();
}
3. How dynamic memory allocation is done using new and delete? Write a program illustrating the use of new and delete.
Solution:
Dynamic Memory Allocation: The process of allocating memory during runtime using pointers.
Keyword use in Dynamic Memory Allocation.
new: Allocates memory on the heap
delete: Deallocates memory from the heap
Example
// new and delete
#include<iostream>
using namespace std;
int main()
{
int size;
cout<<"enter the size of array:\n";
cin>>size;
int *ptr=new int[size];
for(int i=0;i<size;i++)
{
cout<<"Enter the "<<i+1<<" data of the array:\t";
cin>>ptr[i];
}
cout<<"Data you enter are:\n"<<endl;
for(int i=0;i<size;i++)
{
cout<<ptr[i]<<"\t";
}
delete [] ptr;
}
Why Use Dynamic Memory?
-When the size of the data is unknown at compile time
-To create flexible data structures like linked lists, trees, etc.
-More efficient memory use in a large program.
4. What is meant by pass-by-reference? How can we pass arguments by reference using reference variables? Illustrate with an example.
Solution:
Pass-by-reference means passing the actual address (reference) of a variable to a function, so that any changes made inside the function affect the original variable.
We can pass arguments using reference variables by using the '&' symbol in the function parameters.
Example
#include <iostream>
using namespace std;
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 5, y = 10;
cout << "Before swap: x = " << x << ", y = " << y << endl;
swap(x, y);
cout << "After swap: ="<<endl<<"x=" << x <<endl<< ", y = " << y << endl;
return 0;
}
5. Define class and object with suitable examples. How can members of the class be accessed?
Solution:
Class:
- A class is a user-defined data type in C++ that acts as a blueprint for creating objects.
- A class represents a set of related objects.
Object:
- An object can be defined as a data field that has unique attributes and behaviors.
- An object is a real-world instance of a class.
Example:
#include<iostream>
using namespace std;
class Student
{
private:
int roll;
string name;
public:
void setdata(int r,string n)
{
roll=r;
name=n;
}
void display()
{
cout<<"Name:"<<name<<"\n"<<"Roll:"<<roll<<endl;
}
};
int main()
{
Student s1;
s1.setdata(12,"madhav");
s1.display();
}
Members of the Class Can Be Accessed by using
Using the dot (.) operator with the object.
Syntax: objectName.memberName
6. What is an inline function? Why is it used? Write a program to illustrate the inline function.
Solution:
-An inline function is a function in C++ where the code is expanded at the point of function call, instead of jumping to the function definition.
-It is declared using the keyword inline.
It is used for the following reason:
-To reduce function call overhead (especially for small functions).
-To increase execution speed.
-Useful when a function is called many times.
Example:
#include<iostream>
using namespace std;
inline int add(int a,int b)
{
return a+b;
}
int main()
{
int x=5,y=5;
int z=add(x,y);
cout<<"Sum is:"<<z<<endl;
}
7. What is the principal reason for using default arguments? Explain how missing and default arguments are handled.
Solution:
Default arguments in C++ allow us to assign default values to function parameters so that a function can be called with fewer arguments.
Example:
void greet(string name = "User") {
cout << "Hello, " << name << "!" << endl;
}
The principal reason for using default arguments is
-To make functions more flexible and easier to use by allowing optional arguments.
-To reduce function overloading.
Missing and Default Arguments Are Handled:
-If an argument is provided, it is used.
-If an argument is missing, the default value is used.
-Default arguments are always filled from right to left.
Example:
#include<iostream>
using namespace std;
void display(string name = "Guest", int age = 18) {
cout << "Name: " << name << ", Age: " << age << endl;
}
int main() {
display(); // Uses both default arguments
display("Madhav"); // Uses default age
display("Madhav", 20); // Uses provided name and age
return 0;
}
8. Define and write syntax for default arguments. Write a program to display N number of characters using default arguments.
Solution:
Default arguments in C++ allow us to assign default values to function parameters so that a function can be called with fewer arguments.
Syntax:
return_type function_name(parameter1 = default_value1, parameter2 = default_value2, ...);
Program to display N number of characters using default arguments:
#include<iostream>
using namespace std;
// Function with default arguments
void displayChars(char ch = '*', int n = 5) {
for(int i = 0; i < n; i++) {
cout << ch << " ";
}
cout << endl;
}
int main() {
displayChars(); // Uses default: * 5 times
displayChars('#'); // Uses default count: # 5 times
displayChars('$', 3); // Uses both provided values: $ 3 times
return 0;
}
9. Create a function called swaps() that interchanges values using a function template. Write a main to test with multiple types.
Solution:
#include<iostream>
using namespace std;
// Function template
template <typename T>
void swaps(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
int main() {
int x = 10, y = 20;
float f1 = 1.5, f2 = 2.5;
char c1 = 'A', c2 = 'B';
cout << "Before swap - Integers: x = " << x << ", y = " << y << endl;
swaps(x, y);
cout << "After swap - Integers: x = " << x << ", y = " << y << endl;
cout << "\nBefore swap - Floats: f1 = " << f1 << ", f2 = " << f2 << endl;
swaps(f1, f2);
cout << "After swap - Floats: f1 = " << f1 << ", f2 = " << f2 << endl;
cout << "\nBefore swap - Characters: c1 = " << c1 << ", c2 = " << c2 << endl;
swaps(c1, c2);
cout << "After swap - Characters: c1 = " << c1 << ", c2 = " << c2 << endl;
return 0;
}
10. Write a member function reverseit() That reverses a string.
Solution:
#include<iostream>
using namespace std;
class MyString {
public:
string str;
void reverseit() {
int n = str.length();
for(int i = 0; i < n / 2; i++) {
char temp = str[i];
str[i] = str[n - i - 1];
str[n - i - 1] = temp;
}
}
};
int main() {
MyString s;
cout << "Enter a string: ";
cin >> s.str;
s.reverseit();
cout << "Reversed string: " << s.str << endl;
return 0;
}
Some other topics:
Manipulator: It is a special function that can be used to control the format of the input and output stream.
Reference variable: A reference variable provides an alternative name for a variable that is previously defined.
📘 Unit 3: Classes and Objects
1. What is a constructor? Why is it needed in a class? Illustrate types of constructors with examples.
Solution:
Constructor: A constructor is a special member function of a class that is automatically called when an object is created.
A constructor is needed in a class for the following reasons:
-To automatically initialize data members when an object is created.
-Saves time by avoiding manual initialization.
-Supports overloading and flexible object creation.
Constructor types:
a. Default Constructor
-No parameters
b. Parameterized Constructor
-Takes arguments to initialize different objects with different values.
c. Copy Constructor
-Creates a new object by copying values from another existing object.
Example:
#include <iostream>
using namespace std;
class Add {
private:
int a, b;
public:
// 1. Default Constructor
Add() {
a = 0;
b = 0;
cout << "Default Constructor called." << endl;
}
// 2. Parameterized Constructor
Add(int x, int y) {
a = x;
b = y;
cout << "Parameterized Constructor called." << endl;
}
// 3. Copy Constructor
Add(const Add &obj) {
a = obj.a;
b = obj.b;
cout << "Copy Constructor called." << endl;
}
// Method to display the sum
void displaySum() {
cout << "Sum = " << a + b << endl;
}
};
int main() {
// Using default constructor
Add obj1;
obj1.displaySum();
// Using parameterized constructor
Add obj2(10, 20);
obj2.displaySum();
// Using copy constructor
Add obj3 = obj2;
obj3.displaySum();
return 0;
}
2. What is the use of a constructor and a destructor? Write a program illustrating default, parameterized, and copy constructors.
Solution:
Constructor: A constructor is a special member function of a class that is automatically called when an object is created.
Purpose:
-To initialize objects of a class.
-To set default values or custom values to data members.
Destructor:
A destructor is a special member function of a class that is automatically called when an object is destroyed.
Purpose:
-To perform cleanup operations, like releasing memory, closing files, and freeing resources.
Example:
#include <iostream>
using namespace std;
class Add {
private:
int a, b;
public:
// 1. Default Constructor
Add() {
a = 0;
b = 0;
cout << "Default Constructor called." << endl;
}
// 2. Parameterized Constructor
Add(int x, int y) {
a = x;
b = y;
cout << "Parameterized Constructor called." << endl;
}
// 3. Copy Constructor
Add(const Add &obj) {
a = obj.a;
b = obj.b;
cout << "Copy Constructor called." << endl;
}
// Method to display sum
void displaySum() {
cout << "Sum = " << a + b << endl;
}
};
int main() {
// Using default constructor
Add obj1;
obj1.displaySum();
// Using parameterized constructor
Add obj2(10, 20);
obj2.displaySum();
// Using copy constructor
Add obj3 = obj2;
obj3.displaySum();
return 0;
}
3. What is a destructor? List its characteristics. Explain the use of the default copy constructor with an example.
Solution:
Destructor:
A destructor is a special member function of a class that is automatically called when an object is destroyed.
Characteristics of Destructor:
-Same name as the class, but preceded with a tilde ~.
-No return type, not even void.
-No parameters (i.e., cannot be overloaded).
-Called automatically when an object is destroyed.
-Defined only once per class.
-Used to perform cleanup operations before object deletion.
-If not defined by the programmer, the compiler provides a default destructor.
A copy constructor is used to create a new object as a copy of an existing object.
Example:
#include <iostream>
using namespace std;
class Add {
private:
int a, b;
public:
// 1. Default Constructor
Add() {
a = 0;
b = 0;
cout << "Default Constructor called." << endl;
}
// 2. Parameterized Constructor
Add(int x, int y) {
a = x;
b = y;
cout << "Parameterized Constructor called." << endl;
}
// 3. Copy Constructor
Add(const Add &obj) {
a = obj.a;
b = obj.b;
cout << "Copy Constructor called." << endl;
}
// Method to display sum
void displaySum() {
cout << "Sum = " << a + b << endl;
}
};
int main() {
// Using default constructor
Add obj1;
obj1.displaySum();
// Using parameterized constructor
Add obj2(10, 20);
obj2.displaySum();
// Using copy constructor
Add obj3 = obj2;
obj3.displaySum();
return 0;
}
4. What is a destructor? Write a program to show a destructor call (e.g., "memory is released").
Solution:
Destructor:
A destructor is a special member function of a class that is automatically called when an object is destroyed.
#include <iostream>
using namespace std;
class Memory {
public:
Memory() {
cout << "Constructor called: Memory allocated!" << endl;
}
~Memory() {
cout << "Destructor called: Memory released!" << endl;
}
};
int main() {
{
Memory obj; // Constructor is called here
// Destructor is automatically called here when the object goes out of scope
}
return 0;
}
5. Write a C++ program to display the number of objects created using static members.
Solution:
#include <iostream>
using namespace std;
class Counter {
private:
static int count;
public:
Counter() {
count++;
cout << "Object " << count << " created." << endl;
}
static void showCount() {
cout << "Total objects created: " << count << endl;
}
};
int Counter::count = 0;
int main() {
Counter obj1;
Counter obj2;
Counter obj3;
// Display total count
Counter::showCount();
return 0;
}
6. What is this pointer? How can we use it for name conflict resolution? Illustrate with an example.
Solution:
-The 'this' pointer is a C++ keyword that represents the current instance of a class.
-It is a hidden pointer passed as an implicit argument to all non-static member functions.
-It allows member functions to access and manipulate the data members of the objects on which the functions are being called.
#include<stdio.h>
#include<iostream>
#include<sting>
using namespace std;
class student
{
private:
string name;
int id;
public:
student(string name,int id)
{
this->name=name;
this->id=id;
}
void print()
{
cout<<"The given name is "<<name<<endl;
cout<<"The given id is "<<id<<endl;
}
};
int main()
{
student obj1("Madhav",12);
obj1.print();
return 0;
}
7. Write short notes on: this pointer, Static data members.
this pointer:
-The 'this' pointer is a C++ keyword that represents the current instance of a class.
-It is a hidden pointer passed as an implicit argument to all non-static member functions.
-It points to the current object that invoked the member function.
-It allows member functions to access and manipulate the data members of the objects on which the functions are being called.
Syntax: this->member or (*this).member
Useful for:
Resolving naming conflicts.
Returning the current object from member functions for chaining.
Static Data Members
-A static data member belongs to the class itself rather than to any particular object.
-There is only one copy of the static data member shared by all objects of the class.
-Used to keep class-wide information, e.g., counting how many objects are created.
-Declared inside the class with the keyword static.
-Must be defined outside the class (usually in the .cpp file).
-Can be accessed using the class name: ClassName::staticMember or through objects.
📘 Unit 4: Operator Overloading
1. What is operator overloading? Why is it necessary? Write a program for the overloading comparison operator.
Solution:
Operator Overloading: The mechanism of giving an additional task to any operator without affecting its existing semantics.
Operator Overloading is necessary for the following reasons:
- Makes code more intuitive and readable.
- It improves runtime performance.
- Helps mimic natural expressions
Example:
#include<iostream>
using namespace std;
class Student {
public:
int roll;
Student(int r) {
roll = r;
}
// Overloading == operator
bool operator==(const Student &s) {
return roll == s.roll;
}
};
int main() {
Student s1(101);
Student s2(101);
Student s3(202);
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;
}
// Another example
#include<iostream>
using namespace std;
class person
{
private:
int weight;
public:
person(int w=0)
{
weight=w;
}
friend bool operator >(person x, person y);
// friend function
};
bool operator >(person x, person y)
{
return x.weight > y.weight;
}
int main()
{
int w1,w2;
cout<<"Enter the weight of Hari"<<endl;
cin>>w1;
cout<<"Enter the weight of Ram"<<endl;
cin>>w2;
person hari(w1);
person ram(w2);
if(hari>ram)
{
cout<<"Hari is heavy"<<endl;
}
else
{
cout<<"Ram is heavy"<<endl;
}
}
2. Write a program to overload the binary + operator using the friend function to add two heights.
Solution:
#include<iostream>
using namespace std;
class Height {
int feet;
int inches;
public:
Height(int f = 0, int i = 0) {
feet = f;
inches = i;
}
// Friend function to overload +
friend Height operator+(Height h1, Height h2);
void display() {
cout << feet << " feet " << inches << " inches" << endl;
}
};
// Friend function definition
Height operator+(Height h1, Height h2) {
Height temp;
temp.feet = h1.feet + h2.feet;
temp.inches = h1.inches + h2.inches;
// Convert inches to feet if >= 12
if (temp.inches >= 12) {
temp.feet += temp.inches / 12;
temp.inches = temp.inches % 12;
}
return temp;
}
int main() {
Height h1(5, 8); // 5 feet 8 inches
Height h2(6, 7); // 6 feet 7 inches
Height h3 = h1 + h2;
cout << "Height 1: ";
h1.display();
cout << "Height 2: ";
h2.display();
cout << "Total Height: ";
h3.display();
return 0;
}
3. Write a program that overloads extraction and insertion operators.
Solution:
#include <iostream>
#include <string>
using namespace std;
class person {
private:
string name;
int age;
public:
person()
{name=" ";
age=0;
}
friend ostream &operator<<(ostream &output, const person &p);
friend istream &operator>>(istream &input, person &p);
};
ostream &operator<<(ostream &output, const person &p) {
output << "Hello," << endl;
output << "My name is " << p.name << " and my age is " << p.age << endl;
return output;
}
istream &operator>>(istream &input, person &p) {
cout << "Enter your name: ";
input >> p.name;
cout << "Enter your age: ";
input >> p.age;
return input;
}
int main() {
person obj;
cin >> obj;
cout << obj;
return 0;
}
4. Write a program for the overloading comparison operator.
Solution:
#include<iostream>
using namespace std;
class Student {
public:
int roll;
Student(int r) {
roll = r;
}
// Overloading == operator
bool operator==(const Student &s) {
return roll == s.roll;
}
};
int main() {
Student s1(101);
Student s2(101);
Student s3(202);
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;
}
5. Explain the concept of operator overloading. List operators that cannot be overloaded.
Solution:
Operator Overloading: The mechanism of giving an additional task to any operator without affecting its existing semantics.
Operator Overloading is necessary for the following reasons:
- Makes code more intuitive and readable.
- It improves runtime performance.
- Helps mimic natural expressions
Example:
#include<iostream>
using namespace std;
class Student {
public:
int roll;
Student(int r) {
roll = r;
}
// Overloading == operator
bool operator==(const Student &s) {
return roll == s.roll;
}
};
int main() {
Student s1(101);
Student s2(101);
Student s3(202);
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;
}
The operator is not allowed to overload:
- Class members access operator(->)
- Scope resolution operator(::)
- Size operator (size of)
- Conditional operator(?)
- Dereference operator (*) in case of pointer
6. Write a program to add two distance objects using member and friend functions.
Solution:
#include<iostream>
using namespace std;
class Distance {
int feet, inches;
public:
Distance(int f = 0, int i = 0) {
feet = f;
inches = i;
}
// Member function
Distance add(Distance d) {
int f = feet + d.feet;
int i = inches + d.inches;
if (i >= 12) {
f += i / 12;
i %= 12;
}
return Distance(f, i);
}
// Friend function
friend Distance addFriend(Distance d1, Distance d2);
void show() {
cout << feet << " feet " << inches << " inches" << endl;
}
};
// Friend function definition
Distance addFriend(Distance d1, Distance d2) {
int f = d1.feet + d2.feet;
int i = d1.inches + d2.inches;
if (i >= 12) {
f += i / 12;
i %= 12;
}
return Distance(f, i);
}
int main() {
Distance d1(4, 9), d2(5, 7);
Distance result1 = d1.add(d2); // Member function
Distance result2 = addFriend(d1, d2); // Friend function
cout << "Using member function: ";
result1.show();
cout << "Using friend function: ";
result2.show();
return 0;
}
📘 Unit 5: Inheritance
1. Explain the practical implications of protected specifiers in inheritance. List the advantages and disadvantages.
Solution
What is a "protected" specifier in C++?
In C++, we use access specifiers to control how class members (variables and functions) can be accessed.
There are 3 types:
The various class access specifiers are:
-public: Members can be accessed from anywhere (inside and outside the class).
-private: Members can be accessed only inside the class itself.
-protected: Members can be accessed inside the class and in derived (child) classes.
The practical implications of protected specifiers in inheritance are
-Not accessible from outside the class directly.
-But accessible to child classes (classes that inherit from the parent).
Advantages of using protected:
-Allows child classes to access and reuse the parent class's members.
-Keeps the data hidden from outside the class, like private.
-Makes inheritance more useful and flexible without making things public.
Disadvantages of protected in inheritance:
-Breaks full data protection because child classes can still access internal data.
-Increases the risk of bugs if many child classes change the same protected member.
-Makes child classes too dependent on how the parent class is written.
2. What are the various class access specifiers? How does public inheritance differ from private inheritance?
Solution
The various class access specifiers are:
-public: Members can be accessed from anywhere (inside and outside the class).
-private: Members can be accessed only inside the class itself.
-protected: Members can be accessed inside the class and in derived (child) classes.
3. Depict the difference between private and public derivation. Explain the derived class constructor with the program.
Solution
-Public derivation keeps the parent class's public and protected members accessible.
-Private derivation hides the parent class's members from outside, even if they were public.
Derived Class Constructor:
-A derived class constructor is a special member function in a derived class that is responsible for initializing objects of that derived class.
-If the base class has a constructor that takes arguments, then the derived class must call it using an initializer list.
Example:
#include <iostream>
using namespace std;
class Base {
public:
Base(int x) {
cout << "Base class constructor called with value: " << x << endl;}
};
class Derived: public Base {
public:
Derived(int a) : Base(a) { // Calls base class constructor
cout << "Derived class constructor called with value: " << a << endl;
}
};
int main() {
Derived d1(10); // Creating object of derived class
return 0;
}
4. Briefly explain the types of inheritance used in OOP.
Solution
5. Describe the chain of constructors and destructors in inheritance.
Solution
Chain of Constructors in Inheritance:
-When we create an object of a derived class (a class that inherits from another class), the constructor of the base class is called first, then the constructor of the derived class.
-This happens because the base class part of the object needs to be initialized before the derived class can add its own stuff.
-So, the constructor calls go from base class to derived class in order.
Example:
class Base {
public:
Base() {
cout << "Base constructor called\n";
}
};
class Derived : public Base {
public:
Derived() {
cout << "Derived constructor called\n";
}
};
int main() {
Derived obj;
}
Chain of Destructors in Inheritance:
-When the object is destroyed, the destructor of the derived class is called first, then the destructor of the base class.
-This is the opposite order of constructors because the derived class may depend on resources from the base class and should clean up first.
-So, destructor calls go from derived class to base class.
Example:
class Base {
public:
~Base() {
cout << "Base destructor called\n";
}
};
class Derived : public Base {
public:
~Derived() {
cout << "Derived destructor called\n";
}
};
int main() {
Derived obj;
}
6. How does ambiguity arise in multipath inheritance? How can you remove it?
Solution
-In multipath inheritance, a derived class inherits from two or more classes that share a common base class.
-This causes multiple copies of the same base class to be inherited by the derived class.
-When you try to access a member of the base class, the compiler gets confused — it does not know which copy of the base class member to use.
-This confusion is called ambiguity.
Example of Ambiguity in Multipath Inheritance:
#include <iostream>
using namespace std;
class A {
public:
void display() {
cout << "Display from Base Class A" << endl;
}
};
class B : public A { // B inherits from A
};
class C : public A { // C inherits from A
};
class D : public B, public C { // D inherits from both B and C
};
int main() {
D obj;
// Ambiguity: compiler does not know whether to use A from B or A from C
obj.display(); // Compiler error: ambiguous call to display()
return 0;
}
Problem:
D has two copies of class A — one via B and one via C. So when you call obj.display(), compiler says "Which display() do you mean?"
Remove Ambiguity:
-Use Virtual Inheritance to ensure only one shared copy of the base class exists.
Example to Solve the Ambiguity:
#include <iostream>
using namespace std;
class A {
public:
void display() {
cout << "Display from Base Class A" << endl;
}
};
class B : virtual public A { // Virtual inheritance
};
class C : virtual public A { // Virtual inheritance
};
class D : public B, public C { // D inherits from B and C
};
int main() {
D obj;
obj.display(); // No ambiguity, single instance of A is shared
return 0;
}
📘 Unit 6: Virtual Functions, Polymorphism & Miscellaneous
- Difference between compile-time and run-time polymorphism.
2. Explain function template overloading with examples.
Solution
Function Template Overloading:
Function template overloading means creating more than one function template with the same name but different types or numbers of parameters.
Example:
#include<iostream>
using namespace std;
template<typename T>
void display(T a)
{
cout<<"One parameter:"<<a<<endl;
}
template<typename T,typename B>
void display(T a,B b)
{
cout<<"Two parameter:"<<a<<" and "<<b<<endl;
}
int main()
{
display(5);
display(10,"Hello");
3. Explain how exceptions are used with a design that includes multiple exceptions.
Solution
Exception:
An exception is an event or error that occurs during program execution, which interrupts the normal flow of instructions.
Try Block:
-Contains the code that might cause an error.
throw Block:
-Signals (raises) an exception when an error happens.
Catch Block:
-Handles the exception that was thrown.
Example:
#include <iostream>
using namespace std;
int main() {
int neo, deo, result;
cout << "Enter neo and deo: ";
cin >> neo >> deo;
try {
if (deo == 0) {
throw deo; // int exception
}
if (deo < 0) {
throw "Negative divisor not allowed"; // string exception
}
result = neo / deo;
cout << "Division is: " << result << endl;
}
catch (int ex) { // handles int exception
cout << "Error: Division by zero! (divisor = " << ex << ")" << endl;
}
catch (const char* msg) { // handles string exception
cout << "Error: " << msg << endl;
}
return 0;
}
4. What is the use of the reinterpret cast operator? Why do we need a virtual function?
Solution:
The use of the reinterpret cast operator:
-Converts one pointer type to another, even if they are unrelated types.
-Can also convert between pointer and integer types.
-Used for low-level, unsafe conversions where you tell the compiler to treat a block of memory as a different type.
-Does not change the actual bit pattern in memory — only changes the interpretation of the data.
We Need a Virtual Function because of :
-Allows runtime polymorphism.
-Avoiding Code Duplication.
-Working with Collections of Objects.
5. Differentiate between a concrete class and an abstract class. Define class and function templates with syntax.
Concrete Class:
-A normal class we can create objects from.
-Has complete functions with full code.
-You can use it directly in our program.
Abstract Class:
-A special class we cannot create objects from.
-Has at least one function without code (called a pure virtual function).
-Used to make other classes by inheritance. It’s like a blueprint.
Class Template:
-A class template is a blueprint to create classes for different data types.
-It allows us to write one class that works with many types.
Syntax:
template <typename T>
class ClassName {
T data;
public:
void setData(T value) {
data = value;
}
T getData() {
return data;}};
Function Template:
-A function template lets us write one function that works with different data types.
-The compiler creates the right function based on the arguments we use.
Syntax:
template <typename T>
T add(T a, T b) {
return a + b;
}
6. Explain the reason for member function overriding when using virtual functions.
Solution
The reason for member function overriding when using virtual functions:
-To change or customize the behavior of a base class function in a derived class.
-Virtual functions let the program decide at runtime which version of the function to call (base class or derived class), depending on the actual object type.
-This enables runtime polymorphism, so we can use base class pointers to work with different derived class objects, and each will do its own specific task.
-Without overriding virtual functions, the base class function would always be called, even if the object is of a derived class.
Example:
#include <iostream>
using namespace std;
class Base {
public:
virtual void show() { // Virtual function
cout << "Base class show()" << endl;
}
};
class Derived: public Base {
public:
void show() override { // Overriding base class function
cout << "Derived class show()" << endl;
}
};
int main() {
Base* ptr;
Derived d;
ptr = &d; // Base class pointer points to derived class object
ptr->show(); // Calls Derived’s show() because of virtual function
return 0;
}
7. Explain types of polymorphism briefly. Write the roles of polymorphism and how to achieve dynamic polymorphism.
Solution
Types of Polymorphism
a)Compile-time Polymorphism (Static Polymorphism):
-Happens during compilation.
-Examples:
Function overloading (same function name, different parameters)
Operator overloading (custom behavior for operators)
b)Runtime Polymorphism (Dynamic Polymorphism):
-Happens during program execution (runtime).
-Achieved using virtual functions and inheritance.
-Allows the program to decide which function to call based on the actual object type.
Roles of Polymorphism
-Allows one interface to represent different types of objects.
-Helps in code reusability and extensibility.
-Enables flexible and maintainable code by letting functions behave differently for different objects.
-Supports dynamic method dispatch (calling the right function at runtime).
To Achieve Dynamic Polymorphism
-Use inheritance to create a base class and derived classes.
-Declare the base class function as virtual.
-Override the virtual function in derived classes.
-Use a base class pointer or reference to point to derived class objects.
-When you call the function using the base pointer/reference, the derived class’s version is executed at runtime.
8. What is an exception? Why use exception handling? Explain try…catch with an example.
Solution
Exception:
An exception is an event or error that occurs during program execution, which interrupts the normal flow of instructions.
Try Block:
-Contains the code that might cause an error.
throw Block:
-Signals (raises) an exception when an error happens.
Catch Block:
-Handles the exception that was thrown.
Use Exception for
-To detect and handle errors that happen during program execution.
-To separate error-handling code from regular code, making programs cleaner and easier to read.
-To prevent the program from crashing unexpectedly by managing errors gracefully.
-To allow the program to recover or exit safely after an error occurs.
-To handle different types of errors in a controlled way using multiple catch blocks.
Example:
#include <iostream>
using namespace std;
int main() {
int num, den;
cout << "Enter numerator and denominator: ";
cin >> num >> den;
try {
if (den == 0) {
throw "Cannot divide by zero"; // throw exception
}
cout << "Result: " << num / den << endl;
}
catch (const char* msg) { // catch exception
cout << "Error: " << msg << endl;
}
return 0;
}
9. Explain the default action of the copy constructor.
Solution
Default copy constructor:
-The copy constructor is a special constructor used to create a new object as a copy of an existing object.
-If we don’t define our own copy constructor, the compiler provides a default copy constructor automatically.
-The default copy constructor does a shallow copy: it copies all the member variables one by one from the source object to the new object.
-For basic data types (like int, float), it copies the values directly.
-For pointers or objects with dynamic memory, it copies the pointer addresses, not the actual data (this can cause problems like double deletion).
-----imp concept--
Shallow Copy
-Copies all member variables as they are (including pointers).
-Copies the pointer address, not the actual data it points to.
-Both objects end up pointing to the same memory.
-Can cause problems like double deletion or unexpected changes if one object modifies the data.
Deep Copy
-Creates a new copy of the actual data that pointers point to.
-Allocates separate memory for the new object’s pointers.
-Ensures that two objects have independent copies of data.
-Prevents issues like double deletion and unwanted side effects.
📘 Unit 7: Function Templates and Exception Handling
1.Write a program to implement a function template with multiple arguments.
Solution:
#include <iostream>
using namespace std;
// Function template with two different types
template <typename T, typename U>
void display(T a, U b) {
cout << "First argument: " << a << endl;
cout << "Second argument: " << b << endl;
}
int main() {
display(10, 3.14); // int and double
display("Hello", 2023); // const char* and int
return 0;
}
2. When are class templates useful? How to implement a stack with int and string? Illustrate with an example.
class templates are useful when :
-When we want to create a general class that works with different data types (like int, string, float).
-Instead of writing many versions of the same class for each type, we can write one template class.
-It saves time and effort and makes our code more flexible.
To implement a stack with int and string using class templates:
-Create a stack class template that can store any type of data.
-Use the template to make stack objects for int and string types.
Example:
#include <iostream>
using namespace std;
template <typename T>
class Stack {
T arr[5];
int top;
public:
Stack() { top = -1; }
void push(T value) {
if (top < 4) {
arr[++top] = value;
cout << value << " pushed to stack\n";
} else {
cout << "Stack overflow\n";
}
}
void pop() {
if (top >= 0) {
cout << arr[top--] << " popped from stack\n";
} else {
cout << "Stack underflow\n";
}
}
};
int main() {
Stack<int> intStack;
intStack.push(10);
intStack.push(20);
intStack.pop();
Stack<string> stringStack;
stringStack.push("Hello");
stringStack.push("World");
stringStack.pop();
return 0;
}
📘 Unit 8: File Handling.
1.Write a program that stores employee info in a file and displays it in ascending salary order.
Solution:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
struct Employee {
string name;
int salary;
};
// Comparator to sort by salary
bool compare(Employee a, Employee b) {
return a.salary < b.salary;
}
int main() {
vector<Employee> employees = {
{"Alice", 50000},
{"Bob", 45000},
{"Charlie", 60000}
};
// Write employees to file
ofstream outFile("employees.txt");
for (auto e : employees) {
outFile << e.name << " " << e.salary << "\n";
}
outFile.close();
// Read employees from file
vector<Employee> empList;
ifstream inFile("employees.txt");
Employee temp;
while (inFile >> temp.name >> temp.salary) {
empList.push_back(temp);
}
inFile.close();
// Sort employees by salary
sort(empList.begin(), empList.end(), compare);
// Display employees
cout << "Employees in ascending order of salary:\n";
for (auto e : empList) {
cout << e.name << " - " << e.salary << endl;
}
return 0;
}
2.Write a program to illustrate the use of seekg() and tellg().
Solution:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream inFile("data.txt");
// Move to 5th byte in the file
inFile.seekg(5, ios::beg);
// Get current position (should be 5)
streampos pos = inFile.tellg();
cout << "Current position: " << pos << endl;
char ch;
inFile.get(ch); // Read one character at position 5
cout << "Character at position 5: " << ch << endl;
inFile.close();
return 0;
}
3. Write a program that reads the content of the file data.txt and displays it.
Solution:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream inFile("data.txt");
string line;
if (!inFile) {
cout << "File could not be opened." << endl;
return 1;
}
while (getline(inFile, line)) {
cout << line << endl;
}
inFile.close();
return 0;
}
4.What do you mean by the stream? Explain different stream classes for file I/O.
Solution:
Stream:
-A stream is like a flow of data.
-It allows our program to read data from or write data to a source (like a file, keyboard, or screen) one piece at a time.
-Think of it as a pipe that carries data in or out.
5.Write a program that reads and displays data for 2 student objects.
Solution:
#include <iostream>
using namespace std;
class Student {
int id;
string name;
public:
void input() {
cout << "Enter student ID: ";
cin >> id;
cout << "Enter student name: ";
cin >> name;
}
void display() {
cout << "Student ID: " << id << ", Name: " << name << endl;
}
};
int main() {
Student s[2];
for (int i = 0; i < 2; i++) {
cout << "Enter details for student " << i + 1 << ":\n";
s[i].input();
}
cout << "\nStudent Details:\n";
for (int i = 0; i < 2; i++) {
s[i].display();
}
return 0;
}
6.Write a program to overload << and >> operators.
Solution
#include <iostream>
using namespace std;
class Student {
int id;
string name;
public:
// Overload >> to input student data
friend istream& operator>>(istream& in, Student& s) {
cout << "Enter student ID: ";
in >> s.id;
cout << "Enter student name: ";
in >> s.name;
return in;
}
// Overload << to display student data
friend ostream& operator<<(ostream& out, const Student& s) {
out << "Student ID: " << s.id << ", Name: " << s.name << endl;
return out;
}
};
int main() {
Student s1, s2;
cout << "Enter details for student 1:\n";
cin >> s1;
cout << "Enter details for student 2:\n";
cin >> s2;
cout << "\nStudent Details:\n";
cout << s1;
cout << s2;
return 0;
}
7.What is the use of get and getline? Explain with an example.
Soultion
The use of get() and getline() are
get():
-Reads one character from input (including spaces and newlines).
-Useful when we want to read character by character.
getline():
-Reads a whole line (all characters until newline) from input into a string.
-Useful when we want to read a full line including spaces.
Example:
#include <iostream>
#include <string>
using namespace std;
int main() {
char ch;
cout << "Enter a character: ";
cin.get(ch); // reads one character
cout << "You entered: " << ch << endl;
string line;
cout << "Enter a full line: ";
cin.ignore(); // to clear leftover newline from previous input
getline(cin, line); // reads whole line
cout << "You entered: " << line << endl;
return 0;
}
8.Write a program:
a)Class Account with acc no, balance, min_balance (static)
b)Use an array to store and display 5 accounts
Solution:
#include <iostream>
using namespace std;
class Account {
int acc_no;
double balance;
static double min_balance; // Static member
public:
void input() {
cout << "Enter account number: ";
cin >> acc_no;
cout << "Enter balance: ";
cin >> balance;
}
void display() {
cout << "Account No: " << acc_no << ", Balance: " << balance
<< ", Min Balance: " << min_balance << endl;
}
};
// Initialize static member
double Account::min_balance = 1000.0;
int main() {
Account accounts[5];
// Input details for 5 accounts
for (int i = 0; i < 5; i++) {
cout << "Enter details for account " << (i + 1) << ":\n";
accounts[i].input();
}
cout << "\nAccount details:\n";
// Display account details
for (int i = 0; i < 5; i++) {
accounts[i].display();
}
return 0;
}