0% found this document useful (0 votes)
4 views31 pages

(A) Synchronous and Asynchronous Exceptions

The document discusses synchronous and asynchronous exceptions, outlining their definitions and examples. It details the steps for exception handling, including throwing, catching, and propagating exceptions, and explains the differences between logical and syntactic errors. Additionally, it provides code examples for nested try blocks, multiple catch blocks, and custom exceptions for temperature checks.
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)
4 views31 pages

(A) Synchronous and Asynchronous Exceptions

The document discusses synchronous and asynchronous exceptions, outlining their definitions and examples. It details the steps for exception handling, including throwing, catching, and propagating exceptions, and explains the differences between logical and syntactic errors. Additionally, it provides code examples for nested try blocks, multiple catch blocks, and custom exceptions for temperature checks.
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/ 31

GROUP – E

26​ (a) ​ What do you understand by synchronous and asynchronous exception?


​ (b) ​ What are the different steps to perform exception handling? Explain all steps.
​ (c) ​ Write difference between logical and syntactic error.

26. (a) Synchronous and Asynchronous Exceptions:


Synchronous Exceptions:

●​ Synchronous exceptions occur at a specific point in the program's execution, directly after
the occurrence of a particular event or operation.​

●​ These exceptions are typically caused by errors that arise from the code that is currently
being executed.​

For example, if a function tries to divide by zero or access a null pointer, the exception occurs
synchronously as a direct result of the code running at that moment.​

Example of Synchronous Exception:​

int divide(int a, int b) {
return a / b; // This will throw a division by zero exception if b is 0
}

●​

Asynchronous Exceptions:

●​ Asynchronous exceptions occur independently of the normal flow of execution. These


exceptions are triggered by events that are not directly related to the current execution path
of the program, such as external interrupts, system signals, or hardware failures.​

●​ They are often harder to handle because they can happen at any time during the program's
execution, not due to a specific operation.​

Example of Asynchronous Exception:​

○​ Signals such as SIGINT (interrupt signal from the keyboard) are asynchronous
exceptions, where the program can be interrupted by a signal at any point in time.​

26. (b) Steps to Perform Exception Handling:


The General Steps in Exception Handling:

1.​ Exception Throwing:​


○​ An exception is thrown when an error or an unexpected situation occurs during the
execution of the program.​

○​ In C++, exceptions are thrown using the throw keyword.​

○​ The thrown exception can be an instance of a class or a built-in type.​

Example:​

throw 10; // Throws an integer exception

○​
2.​ Exception Catching:​

○​ The thrown exception is caught by the appropriate handler in the try-catch


block.​

○​ The try block contains code that may throw an exception, and the catch block
handles the exception.​

○​ The catch block can specify the type of exception it handles (e.g., int,
std::exception).​

Example:​

try {
throw 10; // Code that throws an exception
} catch (int e) {
cout << "Caught exception: " << e << endl; // Exception handler
}

○​
3.​ Exception Propagation:​

○​ If an exception is not caught within the current function, it is propagated up the call
stack until it is caught by an appropriate catch block.​

○​ If no handler is found, the program may terminate or take other actions depending
on the system’s exception handling setup.​

Example:​

void function1() {
throw 20;
}

void function2() {
function1(); // Exception is propagated from function1 to function2
}
int main() {
try {
function2();
} catch (int e) {
cout << "Caught exception: " << e << endl;
}
return 0;
}

○​
4.​ Exception Handling (Exception Handling Block):​

○​ The exception is caught, and the corresponding exception handling code is executed.
This block provides the programmer with an opportunity to correct the problem or
take appropriate action (logging the error, cleaning up resources, etc.).​

5.​ Exception Propagation & Program Termination:​

○​ If the exception is not handled by the catch blocks in the current scope, it will
propagate to the next higher level, eventually leading to program termination if
unhandled.​

○​ The terminate() function is called when no exception handler is found.​

26. (c) Difference Between Logical and Syntactic Errors:


Aspect Logical Error Syntactic Error

Definition A logical error occurs when the A syntactic error occurs when there is a
program runs but mistake in the syntax of the
produces incorrect code, making it impossible
results due to for the compiler to interpret
flawed logic. it.

Detection Logical errors are usually detected Syntactic errors are detected at compile
by the programmer time by the compiler.
after testing, as
they produce
incorrect results.

Cause Caused by incorrect logic, such as Caused by violations of programming


wrong algorithms, language rules (e.g., missing
incorrect use of semicolons, mismatched
operators, or faulty parentheses, or incorrect
logic. function calls).
Impact The program runs, but it doesn't The program cannot run until the error is
produce the fixed because the code
expected outcome won't compile.
or result.

Example Using an incorrect formula to Missing semicolon at the end of a


calculate the area statement.
of a circle, leading
to wrong results.

Program The program will execute but may The program will not compile, and the
provide wrong execution will not start.
results.

Fix Requires revising the logic or Requires fixing the syntax issues such as
algorithms used in punctuation, keywords, or
the code. statement structure.

Summary:
●​ Synchronous exceptions are errors that occur during the execution of a specific operation,
while asynchronous exceptions are caused by external events, such as interrupts.​

●​ Exception handling involves throwing an exception, catching it with appropriate handlers,


and propagating it if necessary, with proper management of program control flow.​

●​ Logical errors arise from flawed program logic and may lead to incorrect output, while
syntactic errors arise from incorrect code structure and prevent the program from compiling.​

27.​ (a) ​ Can a try block be nested in another try block? Give suitable code example to
illustrate your
​ ​ answer.
​ (b) ​ When we should go for multiple catch blocks for a single try block?
​ (c) ​ Write a suitable code that divides a number by zero and show how it behaves when
exception
​ ​ does not occur and when exception occurs.​ .

28.​ (a) ​ Write a suitable code to illustrate the use of catch(…).


​ (b) ​ Write a C++ program to implement array-index out of bound exception, where
exception is
​ ​ thrown as object.
​ (c) ​ Create two custom exception or user defined exception classes viz. TooHot and
TooCold.
​ ​ Write a program and throw TooHot if the temperature exceeds 40 degrees and throw
​ ​ TooCold if the temperature be less than 20 degrees.

27. (a) Can a try block be nested in another try block?

Yes, a try block can be nested inside another try block. This is useful when you have multiple
potential exceptions in different parts of the code, and you want to handle them separately in
different catch blocks.

In such a case, the inner try block can handle exceptions specific to its code, while the outer try
block can catch exceptions that may occur in the inner try block or the code before the inner try
block.

Example:
#include <iostream>
using namespace std;

int main() {
try {
cout << "Outer try block starts" << endl;

try {
cout << "Inner try block starts" << endl;
int a = 10, b = 0;
if (b == 0) {
throw "Division by zero error!";
}
cout << "Result: " << a / b << endl;
} catch (const char* msg) {
cout << "Caught in inner catch block: " << msg << endl;
}

cout << "Outer try block ends" << endl;


} catch (const char* msg) {
cout << "Caught in outer catch block: " << msg << endl;
}

return 0;
}

Explanation:

●​ The outer try block wraps the entire logic.​

●​ The inner try block specifically handles the division by zero, and its associated catch block
catches and handles that exception.​
●​ The exception handling happens in the inner catch block, and after handling it, control
moves to the outer block.​

Output:
Outer try block starts
Inner try block starts
Caught in inner catch block: Division by zero error!
Outer try block ends

27. (b) When should we go for multiple catch blocks for a single try block?

Multiple catch blocks should be used for a single try block when:

1.​ Different Types of Exceptions:​

○​ You want to handle different types of exceptions differently. For instance, catching an
int exception separately from a char* exception.​

2.​ Handling Different Exception Scenarios:​

○​ When the program can throw multiple types of exceptions, each of which may need
a different recovery strategy or handling logic.​

3.​ Specific Exception Handling:​

○​ If you need specific actions for different types of exceptions, such as cleaning up
resources for certain errors but logging others.​

Example:
#include <iostream>
using namespace std;

int main() {
try {
int choice;
cout << "Enter a number: ";
cin >> choice;

if (choice == 1) {
throw 1; // Integer exception
} else if (choice == 2) {
throw "Invalid input"; // String exception
} else {
throw 3.14; // Double exception
}
}
catch (int e) {
cout << "Caught integer exception: " << e << endl;
}
catch (const char* e) {
cout << "Caught string exception: " << e << endl;
}
catch (double e) {
cout << "Caught double exception: " << e << endl;
}

return 0;
}

Explanation:

●​ Multiple catch blocks are used to catch different types of exceptions (integer, string,
double).​

●​ Each type of exception will be caught by its corresponding catch block, allowing for specific
handling of each type.​

Output Example:
If the user enters 1, the output will be:​

Caught integer exception: 1

●​

27. (c) Write a suitable code that divides a number by zero and show how it
behaves when an exception does not occur and when an exception
occurs.
Code Example:
#include <iostream>
using namespace std;

int divide(int a, int b) {


if (b == 0) {
throw "Error: Division by zero"; // Throwing exception when division by zero
}
return a / b;
}

int main() {
int num1, num2;
cout << "Enter two numbers: ";
cin >> num1 >> num2;
try {
cout << "Trying to divide " << num1 << " by " << num2 << endl;
int result = divide(num1, num2); // Call to divide function
cout << "Result: " << result << endl;
}
catch (const char* msg) {
cout << "Caught exception: " << msg << endl; // Handle exception
}

return 0;
}

Explanation:

●​ The divide() function checks if the divisor is zero and throws an exception if so.​

●​ In the main() function, the user inputs two numbers, and the program tries to divide the
first by the second.​

●​ If division by zero occurs, it is caught by the catch block, and an error message is displayed.​

Behavior:

1.​ When no exception occurs (valid division):​

○​ Input: 10 2​

Output:​

Enter two numbers: 10 2
Trying to divide 10 by 2
Result: 5

○​
2.​ When an exception occurs (division by zero):​

○​ Input: 10 0​

Output:​

Enter two numbers: 10 0
Trying to divide 10 by 0
Caught exception: Error: Division by zero

○​

Explanation of Behavior:
●​ When no exception occurs (i.e., num2 != 0), the program executes normally and prints
the result of the division.​

●​ When an exception occurs (i.e., num2 == 0), the throw statement in the divide()
function is executed, and the program enters the catch block to handle the exception and
print the error message.​

28. (a) Write a suitable code to illustrate the use of catch(…).

In C++, catch(...) is a catch-all handler that can catch any type of exception, regardless of its
type. It is used when you want to catch exceptions that are not explicitly specified in other catch
blocks.

Example:
#include <iostream>
using namespace std;

void throwException(int num) {


if (num < 0) {
throw "Negative number exception!";
} else if (num == 0) {
throw 0; // Integer exception
} else {
throw 3.14; // Float exception
}
}

int main() {
try {
throwException(0); // Change this value to test different exceptions
}
catch (const char* msg) {
cout << "Caught a string exception: " << msg << endl;
}
catch (int num) {
cout << "Caught an integer exception: " << num << endl;
}
catch (double num) {
cout << "Caught a double exception: " << num << endl;
}
catch (...) {
cout << "Caught an unknown exception!" << endl;
}

return 0;
}

Explanation:
●​ The throwException() function throws different types of exceptions based on the input
value.​

●​ In the main() function, we try to call throwException(0) which throws an integer


exception.​

●​ The catch blocks handle specific types of exceptions (const char*, int, double).​

●​ The catch(...) block is a catch-all handler that will catch any other type of exception
that is not explicitly handled by the earlier catch blocks.​

Output for throwException(0):


Caught an integer exception: 0

28. (b) Write a C++ program to implement array-index out of bound exception,
where exception is thrown as object.
In this case, we will throw an exception object to handle out-of-bounds array access.

Example:
#include <iostream>
#include <stdexcept> // For std::out_of_range
using namespace std;

class ArrayIndexOutOfBound {
public:
const char* message;
ArrayIndexOutOfBound(const char* msg) : message(msg) {}
};

void accessArray(int arr[], int size, int index) {


if (index < 0 || index >= size) {
throw ArrayIndexOutOfBound("Array index out of bounds!");
} else {
cout << "Accessing element: " << arr[index] << endl;
}
}

int main() {
int arr[] = {1, 2, 3, 4, 5};
int size = sizeof(arr) / sizeof(arr[0]);

try {
accessArray(arr, size, 6); // Trying to access an out-of-bounds index
} catch (ArrayIndexOutOfBound& e) {
cout << "Exception: " << e.message << endl;
}
return 0;
}

Explanation:

●​ The ArrayIndexOutOfBound class is a custom exception class that stores an error


message.​

●​ The accessArray function checks if the provided index is within bounds; if not, it throws
an ArrayIndexOutOfBound exception object.​

●​ The main() function handles this exception and prints the error message.​

Output:
Exception: Array index out of bounds!

28. (c) Create two custom exception or user-defined exception classes viz. TooHot
and TooCold. Write a program and throw TooHot if the temperature
exceeds 40 degrees and throw TooCold if the temperature is less than
20 degrees.
Example:
#include <iostream>
using namespace std;

// User-defined exception classes


class TooHot {
public:
const char* message;
TooHot(const char* msg) : message(msg) {}
};

class TooCold {
public:
const char* message;
TooCold(const char* msg) : message(msg) {}
};

void checkTemperature(int temperature) {


if (temperature > 40) {
throw TooHot("Temperature is too hot! Exceeds 40 degrees.");
} else if (temperature < 20) {
throw TooCold("Temperature is too cold! Below 20 degrees.");
} else {
cout << "Temperature is normal: " << temperature << " degrees." << endl;
}
}
int main() {
int temperature;

cout << "Enter the temperature: ";


cin >> temperature;

try {
checkTemperature(temperature);
} catch (TooHot& e) {
cout << "Caught exception: " << e.message << endl;
} catch (TooCold& e) {
cout << "Caught exception: " << e.message << endl;
}

return 0;
}

Explanation:

●​ We define two custom exception classes TooHot and TooCold to handle extreme
temperature conditions.​

●​ The checkTemperature() function throws TooHot if the temperature exceeds 40


degrees and TooCold if the temperature is below 20 degrees.​

●​ The main() function catches and handles the exceptions accordingly.​

Output:
If the input temperature is 45:​

Enter the temperature: 45
Caught exception: Temperature is too hot! Exceeds 40 degrees.

1.​

If the input temperature is 15:​



Enter the temperature: 15
Caught exception: Temperature is too cold! Below 20 degrees.

2.​

If the input temperature is 30:​



Enter the temperature: 30
Temperature is normal: 30 degrees.

3.​
Summary:

●​ (a) catch(...) is a generic catch block that can catch any type of exception, including
ones that do not have explicit catch handlers.​

●​ (b) In the array out-of-bound example, an exception object is thrown when accessing an
invalid index in the array.​

●​ (c) In the temperature exception program, two custom exceptions (TooHot and TooCold)
are created to handle extreme temperature conditions.​

29.​ (a) ​ What is generic programming? How do template works?


​ (b) ​ What is function template? Write its syntax.
​ (c) ​ Write a function template for finding the largest number. The array parameters must
be generic data types.

29. (a) What is generic programming? How do templates work?


Generic programming is a programming paradigm that aims to write code that is independent of
specific data types. It allows the same code to be used with different data types, enabling greater
flexibility and reuse. In C++, this is achieved through the use of templates.

Templates in C++ provide a way to write generic functions and classes. Templates allow you to define
functions or classes that work with any data type. When a template is used, the C++ compiler
generates the appropriate code for the data type provided.

How templates work:

●​ A function template defines a generic function that can accept arguments of any data type.​

●​ A class template defines a generic class that can handle any data type.​

●​ The compiler creates specialized versions of these templates when they are used with a
specific type.​

Example:
#include <iostream>
using namespace std;

template <typename T>


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

int main() {
cout << add(3, 5) << endl; // Works with integers
cout << add(2.5, 3.1) << endl; // Works with doubles
return 0;
}

In the above example:

●​ template <typename T> defines a template that works with any data type T.​

●​ When add(3, 5) is called, the compiler creates a version of the add function for int.​

●​ When add(2.5, 3.1) is called, the compiler creates a version of the add function for
double.​

29. (b) What is a function template? Write its syntax.


A function template is a template that allows you to define a function that works with any data type.
The function is defined once, and it can be used with various data types by the compiler generating
the appropriate code at compile-time.

Syntax of a function template:

template <typename T> // T is a placeholder for any data type


ReturnType functionName(ParameterType param1, ParameterType param2, ...) {
// Function body
}

●​ template <typename T>: This declares a template where T is the placeholder for any
data type.​

●​ ReturnType: The return type of the function.​

●​ functionName: The name of the function.​

●​ ParameterType: The type of the function's parameters, which can be any data type.​

Example of a function template:


#include <iostream>
using namespace std;

template <typename T>


T max(T a, T b) {
return (a > b) ? a : b;
}
int main() {
cout << "Max of 3 and 5: " << max(3, 5) << endl; // Works with integers
cout << "Max of 2.5 and 3.1: " << max(2.5, 3.1) << endl; // Works with doubles
cout << "Max of 'A' and 'B': " << max('A', 'B') << endl; // Works with characters
return 0;
}

Explanation:

●​ The max function template works with any type T.​

●​ The function compares the two arguments and returns the larger one.​

●​ The template is instantiated by the compiler at compile time for different types when the
function is called with those types.​

Output:
Max of 3 and 5: 5
Max of 2.5 and 3.1: 3.1
Max of 'A' and 'B': B

29. (c) Write a function template for finding the largest number. The array
parameters must be of generic data types.
Function Template for Finding the Largest Number in an Array:
#include <iostream>
using namespace std;

template <typename T>


T findLargest(T arr[], int size) {
T largest = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > largest) {
largest = arr[i];
}
}
return largest;
}

int main() {
int arrInt[] = {3, 5, 1, 8, 2};
double arrDouble[] = {3.1, 2.5, 4.6, 7.9, 0.3};

cout << "Largest integer: " << findLargest(arrInt, 5) << endl;


cout << "Largest double: " << findLargest(arrDouble, 5) << endl;

return 0;
}

Explanation:

●​ template <typename T>: The template allows the function to work with any data type
T.​

●​ The findLargest() function takes an array and its size as parameters.​

●​ It initializes largest as the first element of the array and iterates through the array to find
the largest element.​

●​ The template works with both integer and floating-point types.​

Output:
Largest integer: 8
Largest double: 7.9

Summary:
●​ (a) Generic programming is a paradigm where code is written independently of specific data
types, and templates in C++ allow this by defining generic functions and classes that work
with any data type.​

●​ (b) A function template is a template that defines a function that can be used with any data
type, and its syntax involves specifying template <typename T> before the function
definition.​

●​ (c) The provided function template findLargest() works with arrays of any data type
and returns the largest number in the array.​

30.​ (a) ​ What is class template? Write a class template to implement a calculator. In this
program write one member function definition outside the class template.
​ (b) ​ What do you mean by overloaded function template? Give an example C++ code of
overloaded function template.

30. (a) What is a class template? Write a class template to implement a calculator.
In this program write one member function definition outside the
class template.
A class template in C++ allows us to create a generic class that can work with any data type. This way,
the same class can be used to handle different types of data, such as int, float, or double,
without having to write separate classes for each type.

Syntax of a Class Template:


template <typename T>
class ClassName {
// Data members and member functions
};

Example of a Class Template to Implement a Calculator:


#include <iostream>
using namespace std;

template <typename T>


class Calculator {
public:
T add(T a, T b);
T subtract(T a, T b);
T multiply(T a, T b);
T divide(T a, T b);
};

// Definition of member functions outside the class template

template <typename T>


T Calculator<T>::add(T a, T b) {
return a + b;
}

template <typename T>


T Calculator<T>::subtract(T a, T b) {
return a - b;
}

template <typename T>


T Calculator<T>::multiply(T a, T b) {
return a * b;
}

template <typename T>


T Calculator<T>::divide(T a, T b) {
if (b != 0)
return a / b;
else
throw "Division by zero error!";
}

int main() {
Calculator<int> calcInt;
Calculator<float> calcFloat;

// Using integer calculator


cout << "Integer addition: " << calcInt.add(10, 20) << endl;
cout << "Integer subtraction: " << calcInt.subtract(10, 5) << endl;

// Using float calculator


cout << "Float addition: " << calcFloat.add(10.5f, 20.3f) << endl;
cout << "Float division: " << calcFloat.divide(10.5f, 2.5f) << endl;

return 0;
}

Explanation:

●​ template <typename T>: Defines the class template for the class Calculator.​

●​ The add, subtract, multiply, and divide functions are defined inside the class
template.​

●​ Member function definitions are provided outside the class template using the template
<typename T> prefix, and Calculator<T>::function_name syntax.​

●​ In main(), objects of the Calculator class are created for int and float types and
used to perform various operations.​

Output:
Integer addition: 30
Integer subtraction: 5
Float addition: 30.8
Float division: 4.2

30. (b) What do you mean by overloaded function template? Give an example C++
code of overloaded function template.
An overloaded function template is a scenario where multiple function templates with the same
name are defined, but they accept different types or numbers of arguments. This allows the same
function name to work with different types, making the code more readable and flexible.

Syntax of Function Template Overloading:


template <typename T>
ReturnType functionName(T arg);

template <typename T>


ReturnType functionName(T arg1, T arg2);
Example of Overloaded Function Templates:
#include <iostream>
using namespace std;

template <typename T>


T display(T a) {
return a;
}

template <typename T>


T display(T a, T b) {
return a + b;
}

int main() {
cout << "Single argument: " << display(10) << endl; // For single argument
cout << "Two arguments: " << display(10, 20) << endl; // For two arguments
cout << "Single argument (double): " << display(10.5) << endl; // For single argument (double)
cout << "Two arguments (double): " << display(10.5, 20.5) << endl; // For two arguments (double)

return 0;
}

Explanation:

●​ Two display functions are defined:​

○​ One that accepts a single argument (display(T a)).​

○​ One that accepts two arguments (display(T a, T b)).​

●​ Both functions are function templates, and the type T is determined when the function is
called.​

●​ The correct overloaded version of the function is chosen based on the number of arguments
passed at compile time.​

Output:
Single argument: 10
Two arguments: 30
Single argument (double): 10.5
Two arguments (double): 31

Key Points:

●​ Function Overloading: Allows multiple functions with the same name but different
signatures (number or types of arguments).​
●​ Template Overloading: Involves the use of overloaded template functions to work with
different data types or different numbers of arguments. This enables greater flexibility and
reuse of code.​

Summary:
●​ (a) A class template is a blueprint for creating classes that can work with any data type. We
implemented a Calculator class template that performs operations like addition, subtraction,
multiplication, and division. Member function definitions were written outside the class
template.​

●​ (b) An overloaded function template allows multiple versions of the same function name to
exist, with each version handling different arguments. We demonstrated function template
overloading by defining multiple versions of the display function to handle different
numbers of arguments.​

31.​ (a) ​ How is namespace is different from a class? Why do we use namespace in our
program?
​ (b) ​ Create a namespace Employee, in which EmpId and EmpName are the two classes.
EmpId class
​ ​ has emp_id data member and show() function, Name class has name data member
and
​ ​ corresponding show() function. Create object for both classes.
​ (c) ​ What is the difference between Template and Macro?

31. (a) How is namespace different from a class? Why do we use namespace in our
program?
Difference between Namespace and Class:

1.​ Purpose:​

○​ Namespace: A namespace is a container used to organize code into logical groups to


avoid name conflicts. It helps manage names of classes, functions, and variables,
ensuring there is no clash when different libraries or parts of a program use similar
names.​

○​ Class: A class is a blueprint for creating objects, encapsulating data for the object
(member variables) and methods that operate on the data (member functions). It is
a fundamental building block of object-oriented programming.​

2.​ Members:​
○​ Namespace: Can hold functions, variables, constants, classes, and other
namespaces. It does not have constructors or destructors.​

○​ Class: Can have member functions, member variables, constructors, destructors, and
operators.​

3.​ Instantiation:​

○​ Namespace: Cannot be instantiated.​

○​ Class: Can be instantiated to create objects.​

4.​ Visibility and Access Control:​

○​ Namespace: Does not have access control modifiers (like public, private,
protected). All members are accessible.​

○​ Class: Has access control (public, private, protected) to manage visibility of data
members and functions.​

Why use Namespace in a Program?

●​ Avoid name conflicts: Namespaces help prevent name clashes, especially when working with
large codebases or multiple libraries. You can encapsulate code into logical groups.​

●​ Code organization: It helps organize functions, classes, and other entities in a modular way.​

●​ Code readability: By using namespaces, you can group related code together, improving
readability and maintainability.​

31. (b) Create a namespace Employee, in which EmpId and EmpName are the two
classes. EmpId class has emp_id data member and show()
function, and EmpName class has name data member and
corresponding show() function. Create objects for both classes.
#include <iostream>
using namespace std;

namespace Employee {
class EmpId {
public:
int emp_id;

// Constructor
EmpId(int id) : emp_id(id) {}

// Function to show employee ID


void show() {
cout << "Employee ID: " << emp_id << endl;
}
};

class EmpName {
public:
string name;

// Constructor
EmpName(string n) : name(n) {}

// Function to show employee name


void show() {
cout << "Employee Name: " << name << endl;
}
};
}

int main() {
// Creating objects of EmpId and EmpName classes inside Employee namespace
Employee::EmpId emp1(101);
Employee::EmpName emp2("John Doe");

// Displaying the details using show() method


emp1.show();
emp2.show();

return 0;
}

Explanation:

●​ We defined a namespace Employee that contains two classes: EmpId and EmpName.​

○​ EmpId class has a data member emp_id and a method show() that prints the
employee's ID.​

○​ EmpName class has a data member name and a method show() that prints the
employee's name.​

●​ In main(), we created objects emp1 of class EmpId and emp2 of class EmpName, and
displayed their information using their respective show() methods.​

Output:
Employee ID: 101
Employee Name: John Doe
31. (c) What is the difference between Template and Macro?
Aspect Template Macro

Definition Templates are a feature in C++ that allows Macros are preprocessor directives
writing generic and in C and C++ that
reusable code that works define code
with any data type. They snippets to be
are part of the language. replaced during
compilation.

Type Safety Templates are type-safe. The compiler Macros are not type-safe; they
checks the types at perform textual
compile-time. substitution
without type
checking.

Functionality Templates allow creating functions and Macros perform simple text
classes that can work with substitution and
any data type. can be used for
constants or code
snippets.

Evaluation Templates are evaluated at compile-time. Macros are expanded by the


The compiler generates preprocessor
code for each type you before compilation,
use with the template. and no type
checking is done.

Scope Templates have scope and are subject to Macros do not have scope and are
C++'s scoping rules. replaced globally
throughout the
code.

Debugging Templates are easier to debug, and errors Macros can be difficult to debug
are caught during because errors are
compilation. often hard to trace
due to text
substitution.

Example of Template:
template <typename T>
T add(T a, T b) {
return a + b;
}

Example of Macro:
#define ADD(a, b) ((a) + (b))

Key Differences:
●​ Type Safety: Templates ensure type safety, whereas macros can lead to unintended behavior
since they do not check types.​

●​ Compile-Time vs Preprocessor: Templates are evaluated by the compiler, while macros are
handled by the preprocessor before compilation starts.​

●​ Error Handling: Template errors are caught by the compiler, making them easier to debug.
Macro errors are harder to debug because they are replaced by text before compilation.​

32.​ (a) ​ Write a program to demonstrate the use of multiple namespaces.


​ (b) ​ What is nested namespace? Write its syntax. Write a C++ code to demonstrate
nested namespace.

32. (a) Write a program to demonstrate the use of multiple namespaces.


In C++, you can have multiple namespaces to organize your code and avoid name conflicts. Let's
demonstrate how multiple namespaces can be used in the same program:

#include <iostream>
using namespace std;

// Define the first namespace


namespace Employee {
void display() {
cout << "Employee Information" << endl;
}
}

// Define the second namespace


namespace Department {
void display() {
cout << "Department Information" << endl;
}
}

int main() {
// Accessing functions from both namespaces
Employee::display(); // Calls the display function in Employee namespace
Department::display(); // Calls the display function in Department namespace

return 0;
}

Explanation:
●​ Employee and Department are two separate namespaces.​

●​ Both namespaces contain a function display(), but they perform different tasks
(displaying information about the employee and department).​

●​ In main(), we access both display() functions using the scope resolution operator (::)
to specify which namespace we are referring to.​

Output:
Employee Information
Department Information

32. (b) What is a nested namespace? Write its syntax. Write a C++ code to
demonstrate nested namespace.
Definition of Nested Namespace:

A nested namespace is a namespace defined inside another namespace. It allows organizing code in
multiple layers, providing a more granular level of namespace encapsulation.

Syntax:
namespace Outer {
namespace Inner {
// Declarations or definitions inside the inner namespace
}
}

You can access members of a nested namespace by using the scope resolution operator for both the
outer and inner namespaces.

Example Code to Demonstrate Nested Namespace:


#include <iostream>
using namespace std;

// Define the outer namespace


namespace Outer {
// Define the inner namespace inside the outer namespace
namespace Inner {
void show() {
cout << "Inside the Inner Namespace" << endl;
}
}
}

int main() {
// Accessing the function inside the inner namespace using the scope resolution operator
Outer::Inner::show(); // Calling the show function inside the inner namespace
return 0;
}

Explanation:

●​ Outer is the outer namespace, and Inner is the nested namespace inside it.​

●​ The function show() is defined inside the Inner namespace.​

●​ In main(), we access the show() function by specifying both the outer and inner
namespaces using the scope resolution operator (::).​

Output:
Inside the Inner Namespace

Using Nested Namespaces in C++17 and Later:

From C++17, you can use the namespace keyword to directly define nested namespaces in a more
concise way:

#include <iostream>
using namespace std;

// C++17 Nested namespace syntax


namespace Outer::Inner {
void show() {
cout << "Inside the Inner Namespace" << endl;
}
}

int main() {
Outer::Inner::show(); // Calling the show function inside the nested namespace
return 0;
}

This syntax is equivalent to the previous version, but it provides a cleaner and more compact way to
define nested namespaces.

33.​ (a) ​ What is the output of the following code snippet?. If you think it is incorrect, rectify
the problem and explain it.
Derived Class Constructor Syntax: Object Slicing (gpt)

​ (b) ​ Write a Father class with data member f_age, and Son class with data member
s_age. If f_age and s_age is a wrong value (say f_age<0, s_age >f_age) then Father
and Son class constructor will throw exception as object. Both of them have int
getAge() function to return their respective age. Implement runtime polymorphism
to implement this problem.

To solve this problem, we will define two classes: Father and Son. The Father class will have a
data member f_age, and the Son class will have a data member s_age. Both classes will have
their constructors throw exceptions if the values for f_age or s_age are invalid. Additionally, both
classes will have a getAge() function to return their respective ages.

Steps:
1.​ Exception Handling: The constructors of both classes will throw an exception if the age
values are invalid (i.e., if f_age < 0 or if s_age > f_age).​

2.​ Runtime Polymorphism: We will implement runtime polymorphism using a virtual function
getAge() that is overridden in the derived Son class.​

3.​ Base Class and Derived Class: The Father class will be the base class, and the Son class
will be the derived class.​

4.​ Exception Propagation: We will use the try-catch blocks to catch exceptions in the main
function.​
Code Implementation:
#include <iostream>
#include <stdexcept>
using namespace std;

class Father {
protected:
int f_age;

public:
// Constructor of Father class
Father(int age) {
if (age < 0) {
throw runtime_error("Father's age cannot be negative");
}
f_age = age;
cout << "Father's age set to: " << f_age << endl;
}

// Virtual function for getting age, to be overridden in Son class


virtual int getAge() {
return f_age;
}

// Virtual destructor
virtual ~Father() {
cout << "Father's object destroyed" << endl;
}
};

class Son : public Father {


private:
int s_age;

public:
// Constructor of Son class
Son(int fatherAge, int sonAge) : Father(fatherAge) {
if (sonAge < 0) {
throw runtime_error("Son's age cannot be negative");
}
if (sonAge > fatherAge) {
throw runtime_error("Son's age cannot be greater than Father's age");
}
s_age = sonAge;
cout << "Son's age set to: " << s_age << endl;
}

// Overriding getAge function for Son class


int getAge() override {
return s_age;
}
// Destructor
~Son() {
cout << "Son's object destroyed" << endl;
}
};

int main() {
try {
// Creating Father and Son objects with invalid values to trigger exceptions
Father* father = new Father(50); // Valid Father
Son* son = new Son(50, 25); // Valid Son

cout << "Father's age: " << father->getAge() << endl;


cout << "Son's age: " << son->getAge() << endl;

// Clean up dynamically allocated objects


delete father;
delete son;

} catch (const exception& e) {


cout << "Exception caught: " << e.what() << endl;
}

try {
// Attempting to create invalid Son and Father objects
Father* invalidFather = new Father(-5); // Invalid Father's age
Son* invalidSon = new Son(50, 60); // Invalid Son's age
} catch (const exception& e) {
cout << "Exception caught: " << e.what() << endl;
}

return 0;
}

Explanation:
1.​ Father Class:​

○​ Father(int age) constructor checks if the age is valid (age must not be
negative). If invalid, it throws a runtime_error exception.​

○​ getAge() function returns the father's age.​

○​ Virtual destructor ensures proper cleanup when the object is destroyed (important
for runtime polymorphism).​

2.​ Son Class:​


○​ Inherits from Father and calls the Father constructor to initialize the father's
age.​

○​ The Son constructor checks that s_age is not negative and that the son's age is less
than or equal to the father's age.​

○​ getAge() is overridden in Son to return the son's age.​

○​ Destructor cleans up resources related to the Son object.​

3.​ Exception Handling:​

○​ We use try-catch blocks in the main() function to catch exceptions thrown by


the constructors of Father and Son.​

4.​ Polymorphism:​

○​ In the main() function, when the base class Father pointer is used to call the
getAge() function, the derived class Son's version of the getAge() function is
invoked due to runtime polymorphism (because getAge() is a virtual function).​

Sample Output:
Father's age set to: 50
Son's age set to: 25
Father's age: 50
Son's age: 25
Father's object destroyed
Son's object destroyed
Exception caught: Father's age cannot be negative
Exception caught: Son's age cannot be greater than Father's age

Key Points:

●​ Runtime Polymorphism: The function getAge() in the base class Father is declared as
virtual, allowing it to be overridden in the derived class Son. The correct function is
called at runtime based on the type of object.​

●​ Exception Handling: The constructors of both Father and Son throw exceptions when
invalid data is provided, and we handle these exceptions using try-catch.​

●​ Inheritance and Virtual Functions: Son inherits from Father, and both classes have virtual
functions (getAge()), enabling runtime polymorphism.​

You might also like