C++ 2023
Q1. Write a short note on the following:
(a) Inline Function
In programming, an inline function typically refers to a function that is expanded or substituted directly at the point where it's called, rather than being called through a separate function call mechanism. This is often achieved through compiler optimization.
In many programming languages, you can use the 'inline' keyword or some equivalent to suggest to the compiler that a particular function should be inlined. The compiler then tries to replace the function call with the actual code of the function at compile time. In some cases, this can lead to performance improvements, as it reduces the overhead of function calls.
#include <iostream>
// Inline function declaration
inline int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 4); // The function call may be replaced with the actual code of the function
std::cout << "Result: " << result << std::endl;
return 0;
}
The 'add' function is declared as 'inline' in the example above. The compiler may choose to inline the function at the call site, resulting in more efficient code.
It's important to note that the 'inline' keyword is typically a hint to the compiler, and the computer may choose not to inline the function if it determines that inlining is not beneficial. Modern compilers often make these decisions based on optimization heuristics and other factors.
(b) Describe the benefits of OOP.
Object-oriented programming (OOP) is a programming paradigm that uses objects which are instances of classes, to organize and structure code. OOP provides several benefits that contribute to better software design, development, and maintenance. Here are some key advantages of object-oriented programming:
1. Modularity:
- OOP promotes modularity by encapsulating the implementation details of a class within the class itself. This encapsulation allows developers to focus on one component at a time, making the code more manageable and easier to understand.
2. Reusability:
- Object-oriented code is often more reusable than procedural code. Once a class has been defined and tested, it can be used in other parts of the program or in different projects without modification. This reuse of code saves development time and reduces the likelihood of errors.
3. Scalability:
- OOP supports scalability by allowing developers to build on existing classes to create new ones. Inheritance, a key concept in OOP, enables the creation of new classes that inherit the properties and behaviors of existing classes, facilitating the extension and customization of software.
4. Abstraction:
- Abstraction involves simplifying complex systems by modeling classes based on their essential characteristics and ignoring irrelevant details. It allows developers to focus on the essential features of an object and hide the unnecessary complexity, making the code more understandable and maintainable.
5. Encapsulation:
- Encapsulation is the building of data and methods that operate on the data into a single unit called a class. This helps in hiding the internal details of an object and exposing only what is necessary. Encapsulation contributes to information hiding and reduces the impact of changes within the codebase.
6. Polymorphism:
- Polymorphism allows objects of different classes to be treated as objects of a common base class. This enables the development of flexible and extensible code. Polymorphism can be achieved through method overriding and interfaces, allowing different objects to respond to the same method call in a way that is specific to their individual class.
7. Easier Maintenance:
- OOP makes code maintenance easier by providing a clear and organized structure. Changes to one part of the system are less likely to affect other parts, and the modularity and encapsulation inherent in OOP makes it easier to locate and fix bugs.
8. Better Problem Solving:
- OOP makes real-world entities and their interactions, making it a natural way to represent and solve complex problems. By structuring code in a way that mirrors the problem domain, developers can create more intuitive and maintainable solutions.
9. Code Understandability:
- OOP promotes code that is closer to human thinking and real-world scenarios. This makes the code more understandable and easier to read, which is essential for collaboration among team members and for maintaining code over time.
10. Adaptability and Flexibility:
- OOP provides a framework for designing and building adaptable and flexible software systems. With features like polymorphism and inheritance, developers can create systems that are easier to modify and extend, supporting changes in requirements and technology.
In summary, object-oriented programming enhances software development by promoting modularity, reusability, scalability, abstraction, encapsulation, polymorphism, easier maintenance, better problem-solving, code understandability, and adaptability. These benefits contribute to the creation of robust, efficient, and maintainable software systems.
(c) New vs Delete
In C++ programming 'New' and 'Delete' are operators used for dynamic memory allocation and deallocation. They are paired operators that allow you to allocate memory on the heap at runtime and then release that memory when it is no longer needed.
1. 'New' Operator:
- The 'new' operator is used to allocate memory for a single object or an array of objects on the heap. It returns a pointer to the allocated memory.
// Allocate memory for a single integer
int *ptr = new int;
// Allocate memory for an array of integers
int *arr = new int[5];
It's important to note that when using 'new', it's the programmer's responsibility to release the allocated memory using the 'delete' operator when it is no longer needed.
2. 'Delete' Operator:
- The 'delete' operator is used to deallocate memory that was previously allocated using the 'new' operator. If the memory was allocated using 'new[]' (for an array), it should be deallocated using 'delete[]'.
// Deallocate memory for a single integer
delete ptr;
// Deallocate memory for an array of integers
delete[] arr;
Failure to release memory properly after using 'new' can result in memory lakes, where the allocated memory is not freed, leading to a loss of available memory over time.
It's important to note that in modern C++, smart pointers such as 'std::unique_ptr' and 'std::shared_ptr' are often recommended over using raw pointers with 'new' and 'delete'. Smart pointers provide automatic memory management and help prevent memory leaks and other memory-related issues.
Here's an example using 'std::unique_ptr':
#include <memory>
int main() {
// Allocate memory for a single integer using std::unique_ptr
std::unique_ptr<int> ptr = std::make_unique<int>();
// No need for explicit delete; memory is automatically released when ptr goes out of scope
return 0;
}
Using smart pointers can make memory management safer and more convenient in C++ programs.
(d) Static Data Member
In C++, a static data member is a class or object member that belongs to the class itself rather than to instances of the classes. It is shared among all instances of the class and can be accessed using the class name rather than an instance of the class. Static data members are declared with the 'static' keyword.
#include <iostream>
class MyClass {
public:
// Static data member
static int staticDataMember;
// Constructor
MyClass(int value) : regularDataMember(value) {}
// Regular member function
void printValues() {
std::cout << "Regular Data Member: " << regularDataMember << std::endl;
std::cout << "Static Data Member: " << staticDataMember << std::endl;
}
private:
// Regular data member
int regularDataMember;
};
// Definition of the static data member outside the class
int MyClass::staticDataMember = 0;
int main() {
// Creating instances of MyClass
MyClass obj1(42);
MyClass obj2(99);
// Accessing the static data member using the class name
MyClass::staticDataMember = 10;
// Accessing the regular and static data members through instances
obj1.printValues();
obj2.printValues();
return 0;
}
- 'static int staticDataMember:' declares a static data member within the 'MyClass'.
- 'int MyClass::staticDataMember = 0;' defines the static data member outside the class and initializes it to a default value.
- 'obj1.printValues();' and 'obj2.printValues();' demonstrate how regular and static data members can be accessed through instances of the class.
It's important to note that static data members are shared among all instances of the class, and they are typically used when you want to maintain common data across all objects of a class rather than having separate copies for each object.
(e) Copy Constructor
A copy constructor in C++ is a special constructor that creates a new object by copying the contents of an existing object. It is used to initialize an object with another object of the same type. The copy constructor is automatically called when an object is passed by value, returned by value, or explicitly when an object is being constructed as a copy of another object.
The syntax for a copy constructor looks like this:
class MyClass {
public:
// Copy constructor
MyClass(const MyClass& other) {
// Perform member-wise copy from 'other' to the current object
// Typically involves copying the values of data members
// May also involve allocating new memory and copying contents if dynamic memory is involved
}
// Other class members and methods...
};
Here's a simple example of a class with a copy constructor:
#include <iostream>
class MyString {
public:
// Constructor
MyString(const char* str) {
if (str != nullptr) {
length = std::strlen(str);
data = new char[length + 1];
std::strcpy(data, str);
} else {
length = 0;
data = nullptr;
}
}
// Copy constructor
MyString(const MyString& other) {
length = other.length;
data = new char[length + 1];
std::strcpy(data, other.data);
}
// Destructor
~MyString() {
delete[] data;
}
// Display the string
void display() const {
std::cout << data << std::endl;
}
private:
char* data;
std::size_t length;
};
int main() {
// Creating an object using the constructor
MyString originalString("Hello, World!");
// Creating a new object using the copy constructor
MyString copiedString(originalString);
// Displaying the original and copied strings
std::cout << "Original String: ";
originalString.display();
std::cout << "Copied String: ";
copiedString.display();
return 0;
}
In this example, the 'MyString' class has a copy constructor that performs a deep copy of the data to ensure that each object has its own dynamically allocated memory for the character array. The copy constructor is used when creating the 'copiedString' object, making a duplicate of the 'originalString'.
(f) Virtual Base Class
In C++, a virtual base class is a class that serves as a common base class for multiple derived classes within an inheritance hierarchy. The use of a virtual base class helps to prevent ambiguity and duplication of base class members when multiple paths of inheritance lead to a common ancestor.
Consider the following example:
#include <iostream>
// Virtual base class
class Animal {
public:
Animal(const std::string& name) : name(name) {}
void eat() const {
std::cout << name << " is eating." << std::endl;
}
void sleep() const {
std::cout << name << " is sleeping." << std::endl;
}
private:
std::string name;
};
// Derived class 1
class Mammal: public virtual Animal {
public:
Mammal(const std::string& name) : Animal(name) {}
void giveBirth() const {
std::cout << "Mammal giving birth." << std::endl;
}
};
// Derived class 2
class Bird: public virtual Animal {
public:
Bird(const std::string& name) : Animal(name) {}
void layEggs() const {
std::cout << "Bird laying eggs." << std::endl;
}
};
// Derived class combining Mammal and Bird
class Platypus: public Mammal, public Bird {
public:
Platypus(const std::string& name) : Animal(name), Mammal(name), Bird(name) {}
};
int main() {
Platypus perry("Perry the Platypus");
// Calling methods from the virtual base class
perry.eat(); // Calls Animal's eat()
perry.sleep(); // Calls Animal's sleep()
// Calling methods from the derived classes
perry.giveBirth(); // Calls Mammal's giveBirth()
perry.layEggs(); // Calls Bird's layEggs()
return 0;
}
In this example:
- 'Animal' is a virtual base class with common functionalities.
- 'Mammal' and 'Bird' are derived classes that inherit virtually from 'Animal'.
- The 'Platypus' class inherits both 'Mammal' and 'Bird'. Since both 'Mammal' and 'Bird' virtually inherit from 'Animal', the 'Platypus' class does not contain two separate instances of 'Animal'.
Using the 'virtual' keyword when inheriting helps to prevent the "diamond problem," which is a form of ambiguity that can arise when a class inherits from two classes that have a common base class. The 'virtual' inheritance ensures that there is only one instance of the virtual base class in the final derived class.
(G) Friend Function
- A friend function is a function that is not a member of a class but is granted access to the class's private and protected members.
- It is declared with the friend keyword in the class definition.
#include <iostream>
using namespace std;
// Declaration of a class named Complex
class Complex {
int a, b;
// Declaration of a friend function named Sum
friend Complex Sum(Complex c1, Complex c2);
public:
// Member function to input values for 'a' and 'b'
void getdata() {
cout << "\n Enter the value of a - ";
cin >> a;
cout << " Enter the value of b - ";
cin >> b;
}
// Member function to print the values of 'a' and 'b'
void printNo() {
cout << "\n The value of a is : " << a << endl;
cout << " The value of b is : " << b << endl;
}
};
// Definition of the friend function Sum
Complex Sum(Complex c1, Complex c2) {
Complex c3;
c3.a = c1.a + c2.a;
c3.b = c1.b + c2.b;
return c3;
}
// The starting point of the program
int main() {
// Create objects of Complex class
Complex c1, c2, sum;
// Input values for c1 and c2
c1.getdata();
c2.getdata();
// Call the friend function Sum to add c1 and c2, store result in sum
sum = Sum(c1, c2);
// Print the result
sum.printNo();
// Indicate successful program execution
return 0;
}
(H) Class Template
- A class template in C++ allows you to define a generic class that can work with different data types.
- It provides a way to create classes with members that can vary in type.
(I) This Pointer
- The 'this pointer' is a pointer available in C++ that points to the object for which the member function is called.
- It is used to differentiate between the calling object's data members and local variables with the same names.
#include<iostream>
using namespace std;
class MyClass {
private:
int value;
public:
void setValue(int value) {
// Using the this pointer to differentiate between
// the class member and the local variable
this->value = value;
}
void displayValue() {
cout << "Value: " << value << endl;
}
};
int main() {
MyClass obj;
obj.setValue(42);
obj.displayValue();
return 0;
}
In this example, the 'this pointer' is used within the setValue function to assign the value passed as a parameter to the class member variable.
It helps distinguish between the local variable and the class member with the same name.
(J) Early Vs Late Binding
- Early Binding (Static Binding): The association between a function call and the function definition is determined at compile time.
- This is also known as compile-time polymorphism.
- In the early binding example, the function calls are resolved at compile time based on the declared type.
- Late Binding (Dynamic Binding): The association between a function call and the function definition is determined at runtime.
- This is also known as runtime polymorphism and is achieved through virtual functions.
- In the late binding example, virtual functions are used, and the function calls are resolved at runtime.
Q2. (a) Explain the following terms:
(i) Literals
Literals are constant values that represent fixed values and data types in a program. In C++, there are several types of literals, including:
- Integer Literals: Represent whole numbers without any decimal point (e.g., 42).
- Floating Point Literals: Represent numbers with a decimal point or in scientific notation (e.g., 3.14 or 2.5e3).
- Character Literals: Represent individual characters enclosed in single quotes (e.g., 'A').
- String Literals: Represent sequences of characters enclosed in double quotes (e.g., "Hello").
- Boolean Literals: Represent either true or false.
- Nullptr Literal: Represent a null pointer and is denoted by the keyword nullptr.
(ii) Implicit Conversion
- Implicit conversion, also known as type conversion, refers to the automatic conversion of one data type to another by the compiler without the need for explicit instructions from the programmer.
- This conversion occurs when an expression involving different data types is encountered.
- Implicit conversion is convenient but should be used with caution, as it may lead to unexpected behavior if not handled carefully.
(b) Write a program that will find out whether the given number is even or odd. If it is an odd number then find out whether it is prime or not?
#include<iostream>
#include<cmath> // Required for sqrt function
using namespace std;
// Function to check if a number is prime
bool isPrime(int num) {
if (num <= 1) {
return false;
}
for (int i = 2; i <= sqrt(num); ++i) {
if (num % i == 0) {
return false;
}
}
return true;
}
int main() {
// Input
int number;
cout << "Enter a number: ";
cin >> number;
// Check if the number is even or odd
if (number % 2 == 0) {
cout << number << " is an even number." << endl;
} else {
cout << number << " is an odd number." << endl;
// Check if the odd number is prime
if (isPrime(number)) {
cout << number << " is a prime number." << endl;
} else {
cout << number << " is not a prime number." << endl;
}
}
return 0;
}
Q3. (a) Illustrate the comparison between C and C++.
Object Oriented Programming (OOP):
- C: Procedural programming language without native support for OOP concepts.
- C++: Extends C with features like classes, objects, inheritance, and polymorphism, providing a comprehensive OOP framework.
Standard Template Library (STL):
- C: Lacks a standardized template library.
- C++: Includes the STL, offering a collection of template classes and functions for common data structures and algorithms.
Memory Management:
- C: Relies on manual memory management using functions like malloc and free.
- C++: Supports both manual and automatic memory management through features like constructors, destructors, and the new and delete operators.
Function Overloading:
- C: Does not support function overloading.
- C++: Allows multiple functions with the same name but different parameter lists, enhancing code readability and flexibility.
(b) Describe the concepts of parameter passing by value, reference, and pointer with the help of an example.
1. Parameter passing by Value:
- In parameter passing by value, the actual value of the argument is passed to the function.
- Changes made to the parameter within the function do not affect the original value outside the function.
#include <iostream>
using namespace std;
class Swap
{
public:
int a, b, swap;
void getData()
{
cout << "enter the value of a \n";
cin >> a;
cout << " \nenter the value of b \n";
cin >> b;
}
void SwapByValue()
{
swap = a;
a = b;
b = swap;
}
void DisplayData()
{
cout << "swaped value of a is "
<< a;
cout << " swaped value of b is "
<< b;
}
};
int main()
{
Swap s;
s.getData();
s.SwapByValue();
s.DisplayData();
}
2. Parameter Passing by reference:
- In parameter passing by reference, the memory address of the actual argument is passed to the function.
- Changes made to the parameter within the function directly affect the original value outside the function.
// call by reference using class
#include <iostream>
using namespace std;
class Swap
{
// int a, b;
// priavte, protected
public:
void swapReference(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
};
int main()
{
Swap s;
int x, y;
cout << " Please enter the value of x - ";
cin >> x;
cout << "\n Please enter the value of y - ";
cin >> y;
s.swapReference(x, y);
cout << " \n swapped value of x is "
<< x;
cout << "\n swapped value of y is "
<< y;
return 0;
}
3. Parameter Passing by Pointer:
- In the parameter passing by pointer, the memory address (pointer) of the actual argument is passed to the function.
- Like passing by reference, changes made to the parameter through the pointer affect the original value outside the function.
#include <iostream>
using namespace std;
class Swap
{
public:
void swapPointer(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
};
int main()
{
Swap s;
int x, y;
cout << "Please enter the value of x: ";
cin >> x;
cout << "Please enter the value of y: ";
cin >> y;
s.swapPointer(&x, &y);
cout << "\nSwapped value of x is " << x;
cout << "\nSwapped value of y is " << y;
return 0;
}
Q4. (a) Explain the concept of constructor overloading and function overloading.
Constructor Overloading:
- Constructor overloading in C++ involves defining multiple constructors within a class, each with a different set of parameters.
- Purpose: Allows an object to be initialized in different ways based on the number of types of parameters provided during object creation.
Example:
#include<iostream>
using namespace std;
class MyClass {
public:
// Default constructor
MyClass() {
cout << "Default constructor called" << endl;
}
// Parameterized constructor
MyClass(int value) {
cout << "Parameterized constructor called with value: " << value << endl;
}
};
int main() {
// Creating objects using different constructors
MyClass obj1; // Default constructor
MyClass obj2(42); // Parameterized constructor
return 0;
}
Function Overloading:
- Function overloading allows multiple functions with the same name but different parameter lists within the same scope.
- Purpose: Provides flexibility in using functions with various argument types or numbers of arguments.
Example:
#include<iostream>
using namespace std;
// Function overloading
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int main() {
// Using overloaded functions
cout << "Sum (int): " << add(5, 7) << endl;
cout << "Sum (double): " << add(3.5, 4.2) << endl;
return 0;
}
(b) What do you understand by access specifiers? What are these access specifiers?
- In C++, access specifiers are keywords used in class definitions to control the visibility and accessibility of class members (attributes and methods) from outside the class.
- They determine how the class's members can be accessed and modified by other parts of the program.
Types of Access Specifiers:
Public:
- Members declared as public are accessible from any part of the program including outside the class.
class MyClass {
public:
int publicVar;
void publicMethod() {
// Code here
}
};
Private:
- Members are declared as private and are only accessible within the class. They cannot be accessed directly from outside the class.
class MyClass {
private:
int privateVar;
void privateMethod() {
// Code here
}
};
Protected:
- Similar to private, members declared as protected are accessible within the class and its derived class (in the context of inheritance).
class BaseClass {
protected:
int protectedVar;
};
class DerivedClass: public BaseClass {
// Can access protectedVar here
};
Inheritance:
- Access specifiers play a role in determining the visibility of members in derived classes when using inheritance
- They define the level of access to base class members in the derived class.
Q5. (a) Define a class Teacher with the following specifications:
Private numbers:
Name 20 characters
Subject 10 characters
Basic, DA, HRA float
Salary float
Calculate() function computes the salary and returns it. Salary is sum of Basic, DA, HRA
Public members:
Readdata() function accepts the data values and invokes the calculate function.
Displaydata() function prints the data on the screen.
Class Definition for Teacher:
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
class Teacher {
private:
char Name[21];
char Subject[11];
float Basic;
float DA;
float HRA;
float Salary;
// Private member function to calculate salary
void Calculate() {
Salary = Basic + DA + HRA;
}
public:
// Public member function to read data and invoke Calculate
void ReadData() {
cout << "Enter Teacher's Name (up to 20 characters): ";
cin.ignore(); // Clear the input buffer
cin.getline(Name, 21);
cout << "Enter Subject (up to 10 characters): ";
cin.getline(Subject, 11);
cout << "Enter Basic Salary: ";
cin >> Basic;
cout << "Enter DA: ";
cin >> DA;
cout << "Enter HRA: ";
cin >> HRA;
Calculate(); // Invoke the Calculate function
}
// Public member function to display data
void DisplayData() {
cout << "\nTeacher's Information:\n";
cout << "Name: " << Name << endl;
cout << "Subject: " << Subject << endl;
cout << fixed << setprecision(2);
cout << "Basic Salary: $" << Basic << endl;
cout << "DA: $" << DA << endl;
cout << "HRA: $" << HRA << endl;
cout << "Total Salary: $" << Salary << endl;
}
};
int main() {
Teacher teacher;
// Read data and display information
teacher.ReadData();
teacher.DisplayData();
return 0;
}
(b) What are the special properties of a constructor?
Automatic Invocation:
- Constructors are automatically invoked when an object of the class is created.
- They ensure that necessary setup operations are performed before the object is used.
Same Name as Class:
- Constructors have the same name as the class and do not have a return type.
- They are used to initialize the object's state during creation.
Multiple Constructors (Overloading):
- A class can have multiple constructors, allowing different ways to initialize objects based on the provided arguments.
- Constructor overloading provides flexibility in object creation.
Initialization of Member Variables:
- The constructor initializes the member variables of the class, ensuring that the object starts with a consistent and valid state.
Q6. (a) How can a data member and member function present in a public mode in class be accessed through a pointer object? Explain it by taking an example.
- Accessing Public Data Members and Member Functions through a pointer.
- In C++, data members and member functions of a class can be accessed through a pointer to an object.
- This involves using the arrow operator (->) with the pointer to access members. Here's an example to illustrate the concept:
#include<iostream>
#include<string>
using namespace std;
class Student {
public:
// Public data members
string name;
int age;
// Public member function
void displayInfo() {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
}
};
int main() {
// Creating an object of the class
Student studentObj;
studentObj.name = "John Doe";
studentObj.age = 20;
// Creating a pointer to the object
Student *ptrStudent = &studentObj;
// Accessing public data members through the pointer
cout << "Name through pointer: " << ptrStudent->name << endl;
cout << "Age through pointer: " << ptrStudent->age << endl;
// Accessing public member function through the pointer
ptrStudent->displayInfo();
return 0;
}
Explanation:
Object Creation:
- An object of the class Student named and StudentObj is created.
Pointer Creation:
- A pointer ptrStudent is created, pointing to the address of the studentobj.
Accessing Public Data Members:
- Public data members (name and age) are accessed through the pointer using the arrow operator (->).
Accessing Public Member Function:
- The public member function displayInfo() is accessed through the pointer using the arrow operator (->).
(b) Create a class COMPLEX and overload binary + operator to add objects. Using friend functions.
Overloading Binary Operator for Addition in Class COMPLEX using Friend Function
#include<iostream>
using namespace std;
class COMPLEX {
private:
float real;
float imag;
public:
// Constructor to initialize complex numbers
COMPLEX(float r = 0, float i = 0) : real(r), imag(i) {}
// Friend function to overload binary operator '+'
friend COMPLEX operator+(const COMPLEX& c1, const COMPLEX& c2);
// Member function to display complex number
void display() {
cout << "Complex Number: " << real << " + " << imag << "i" << endl;
}
};
// Definition of the friend function to overload '+'
COMPLEX operator+(const COMPLEX& c1, const COMPLEX& c2) {
COMPLEX temp;
temp.real = c1.real + c2.real;
temp.imag = c1.imag + c2.imag;
return temp;
}
int main() {
// Creating two complex numbers
COMPLEX complex1(3.0, 4.0);
COMPLEX complex2(1.5, 2.5);
// Using the overloaded '+' operator to add complex numbers
COMPLEX sum = complex1 + complex2;
// Displaying the result
cout << "Sum of Complex Numbers:" << endl;
sum.display();
return 0;
}
Explanation
- COMPLEX: This is the name of the class. It looks like this class represents complex numbers.
- (float r = 0, float i = 0): This part defines the constructor for the class.
- : real(r), imag(i): This is the member initializerlist. It is used to initialize the member variables of the class (real and imag) with the values passed to the constructor.
- Friend Function: The operator+ function is declared as a friend function inside the class to allow it to access private members.
- Operator overloading: The operator+ function is defined outside the class to perform the addition of complex numbers.
- Main Function: Two complex numbers (complex1 and complex2) are created.
- The overloaded + operator is used to add these complex numbers, and the result is stored in the sum object.
- Displaying Result: The result of the addition is displayed using the display member function.
Q7 Define an inheritance and its advantages? Explain the types of inheritance.
- Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a class (subclass or derived class) to inherit properties and behaviors from another class (base class or parent class).
- The subclass can reuse and extend the functionality of the base class, promoting code reusability and modularity.
Advantages of Inheritance:
- Code Reusability: Inheritance enables the reuse of code from existing classes, reducing redundancy.
- Extensibility: Subclasses can extend the functionality of the base class by adding new attributes and methods.
- Inheritance facilitates polymorphism, allowing objects of the derived class to be treated as objects of the base class.
Types of Inheritance:
Single Inheritance:
A class inherits from only one base class.
class Base {
// Base class definition
};
class Derived : public Base {
// Derived class inherits from Base
};
Multiple Inheritance:
A class inherits from more than one base class.
Example:
class Base1 {
// Base class definition
};
class Base2 {
// Another base class definition
};
class Derived : public Base1, public Base2 {
// Derived class inherits from multiple base classes
};
Multiple Inheritance:
A class inheritance from more than one base class.
class Base1 {
// Base class definition
};
class Base2 {
// Another base class definition
};
class Derived : public Base1, public Base2 {
// Derived class inherits from multiple base classes
};
Hierarchical Inheritance:
Multiple classes are derived from a single base class.
class Base {
// Base class definition
};
class Derived1 : public Base {
// First derived class
};
class Derived2 : public Base {
// Second derived class
};
Hybrid(Virtual) Inheritance:
A combination of multiple and hierarchical inheritance, involving the use of virtual base classes.
class Base {
// Base class definition
};
class Derived1 : virtual public Base {
// First derived class with virtual inheritance
};
class Derived2 : virtual public Base {
// Second derived class with virtual inheritance
};
class FinalDerived : public Derived1, public Derived2 {
// Final derived class
};
Q8. (a) What do you mean by generic programming? Write a program to swap any two different types of variables using a function template.
- Generic programming is a programming paradigm that emphasizes writing code in a way that is independent of data types.
- It allows algorithms and data structures to be written generically, making them applicable to various types without the need for duplication.
#include<iostream>
using namespace std;
// Function template for swapping any two variables of different types
template <typename T>
void swapVariables(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
int main() {
// Example with integer variables
int num1 = 5, num2 = 10;
cout << "Before swapping (int): " << num1 << ", " << num2 << endl;
swapVariables(num1, num2);
cout << "After swapping (int): " << num1 << ", " << num2 << endl;
// Example with double variables
double double1 = 3.14, double2 = 2.718;
cout << "Before swapping (double): " << double1 << ", " << double2 << endl;
swapVariables(double1, double2);
cout << "After swapping (double): " << double1 << ", " << double2 << endl;
return 0;
}
Explanation:
Function Template (Swap Variable):
- The swapVariable function template is defined to swap two variables of any data type.
- The template parameter typename T allows the function to work with variables of different types.
Main Function:
- The program demonstrates the use of the swapVariables function template with integer and double variables.
- Variables are passed to the function, and their values are swapped.
Output: The program outputs the values of variables before and after swapping for both integer and double examples.
(b) Create a class Stack that throws Overflow and Underflow exceptions.
#include<iostream>
#include<stdexcept>
using namespace std;
class Stack {
private:
static const int MAX_SIZE = 5; // Maximum size of the stack
int data[MAX_SIZE]; // Array to store stack elements
int top; // Index of the top element
public:
// Constructor to initialize the stack
Stack() : top(-1) {}
// Function to push an element onto the stack
void push(int value) {
if (top == MAX_SIZE - 1) {
// Throw Overflow exception if the stack is full
throw overflow_error("Stack Overflow");
}
data[++top] = value;
}
// Function to pop an element from the stack
int pop() {
if (top == -1) {
// Throw Underflow exception if the stack is empty
throw underflow_error("Stack Underflow");
}
return data[top--];
}
// Function to display the elements of the stack
void display() {
if (top == -1) {
cout << "Stack is empty." << endl;
return;
}
cout << "Stack elements: ";
for (int i = 0; i <= top; ++i) {
cout << data[i] << " ";
}
cout << endl;
}
};
int main() {
try {
// Creating an instance of the Stack class
Stack myStack;
// Pushing elements onto the stack
myStack.push(10);
myStack.push(20);
myStack.push(30);
myStack.display();
// Popping elements from the stack
cout << "Popped: " << myStack.pop() << endl;
cout << "Popped: " << myStack.pop() << endl;
myStack.display();
// Trying to pop from an empty stack (Underflow)
// Uncommenting the next line will result in an underflow exception
// cout << "Popped: " << myStack.pop() << endl;
// Pushing more elements to fill the stack (Overflow)
myStack.push(40);
myStack.push(50);
myStack.push(60);
myStack.push(70); // Uncommenting this line will result in an overflow exception
myStack.display();
} catch (const exception &e) {
// Catching and handling exceptions
cerr << "Exception: " << e.what() << endl;
}
return 0;
}
Explanation:
Stack Class:
- The stack class is implemented with an array to store elements and a variable to track the top of the stock.
- The push function adds an element to the stack, and the pop function removes an element.
- The display function prints the elements of the stack.
Exception Handling:
- The program uses the std::overflow_error and std::underflow_error exceptions to handle stack overflow and underflow situations.
- When an overflow or underflow condition is detected, an exception is thrown with an appropriate error message.
Main Function:
- The main function demonstrates the use of the Stack class by pushing and popping elements from the stack.
- It also includes examples of stack underflow and overflow scenarios, with appropriate exception handling.
Explanation and Modification:
- The provided code demonstrates inheritance in C++, where the Programmer class is derived from the Employee base class.
- Here are some explanations and a slight modification for clarity:
1. Visibility Modes:
- The Employee class has two data members: id and salary, with a parameterized constructor to initialize them.
- The Programmer class is derived publicly from the Employee class, which means that both the ID and salary of the base class are publicly inherited.
2. Object Creation:
- Objects of the Employee class (Harry and Rohan) are created and their salary values are accessed.
- An object of the Programmer class (p) is created, and its languageCode, id, and the getData method are accessed.
Modification for clarity: The getData method in the Programmer class attempts to access the id member directly, but it is already accessible due to public inheritance. The method can be simplified.
#include <iostream>
using namespace std;
// Base Class
class Employee
{
public:
int id;
float salary;
// Parameterized constructor
Employee(int inpId)
{
id = inpId;
salary = 34.0;
}
// Default constructor
Employee() {}
};
// Derived Class (Programmer) from Employee Base class
class Programmer : public Employee
{
public:
int languageCode;
// Parameterized constructor
Programmer(int inpId) : Employee(inpId)
{
languageCode = 9;
}
// Simplified method for clarity
void getData()
{
cout << id << endl;
}
};
int main()
{
// Creating objects of Employee class
Employee Harry(1), Rohan(2);
cout << "Harry's Salary: " << harry.salary << endl;
cout << "Rohan's Salary: " << rohan.salary << endl;
// Creating object of Programmer class
Programmer p(10);
cout << "Language Code: " << p.languageCode << endl;
cout << "ID: " << p.id << endl;
p.getData();
return 0;
}
Q9. (a) Explain the following terms:
(i) seekg() (ii) getline() (iii) write()
(i) seekg:
- seekg is a function in C++ used for setting the position of the get pointer (stream pointer) within a file.
- Usage: streampos seekg(streampos pos);
- It is commonly used with the ifstream (input file stream) to move the read pointer to a specified position within the file.
- pos is the absolute position within the file where the get pointer will be moved.
(ii) getline:
- getline is a function in C++ used for reading a line from an input stream (such as a file or cin) into a string.
- istream& getline (stream& is, string& str, char delim = '/n');
- It reads characters from the input stream until the specified delimiter ('/n' by default) or the end of the file is encountered.
- The read characters are stored in the string str.
(iii) Wite:
- write is a functioning C++ used for writing a block of data directly to an output stream (such as a file).
- Usage:iostream& write(const char*s, streamsize n);
- It writes n characters from the character array s to the output stream.
- It is commonly used with the ofstream(output file stream) to write binary data.
(b) What is the File Access Mode? Describe the various file modes.
File access modes in C++ determine how a file can be opened and manipulated.
They are specified when opening a file using a class such as lifestream or stream. Here are the various file access modes:
- 1. ios::in (Input):
- Opens a file for reading.
- Used with classes like ifstream.
- ifstream inputfile("example.txt",ios::in);
- 2. ios::out(Output):
- Opens a file for writing.
- If the file already exists, its contents are truncated.
- Used with classes like ofstream.
- ofstream outputFile("output.txt", ios::out);
- 3. ios::app (Append):
- Opens a file for writing, but appends new data at the end of the file.
- Existing data is not truncated.
- ofstream appendFile("log.txt",ios::app);
- 4. ios::ate (At End):
- Sets the initial position at the end of the file.
- Useful for both reading and writing.
- fstream file ("data.txt", ios::ate);
- 5. ios::binary (Binary):
- Treats the file as binary file instead of a text file.
- Useful when reading or writing non-text data.
- ofstream binary file ("data.bin", ios::binary);
- 6. ios::tunc (Truncate):
- Used with the ios::out mode to truncate file if it already exists.
- if the file does not exist, it is created.
- ofstream truncFile ("output.txt", ios::out | ios::trunc);