Unit 6: Exception Handling, Templates and Standard Template Library - Subjective Questions
CSE202 — Object Oriented Programming • Practice Questions with Detailed Answers
20 questions
Define an exception in C++. Why is exception handling preferred over traditional error-handling techniques?
Exception: An exception is an abnormal condition or runtime error that interrupts the normal flow of a program. In C++, an exception is represented by a value or object thrown by the code that detects the error.
Advantages of exception handling:
- It separates error-handling code from normal program logic.
- An error can be handled at a different level of the call stack.
- Exceptions can carry detailed information through objects.
- Errors cannot be ignored as easily as error codes.
- Different error types can be handled by different
catchblocks. - Stack unwinding automatically destroys local objects, supporting resource cleanup.
Traditional techniques such as return codes require every caller to check the returned value. Exception handling provides a structured mechanism using try, throw, and catch.
Explain the exception-handling mechanism in C++ using try, throw, and catch.
The C++ exception-handling mechanism consists of three main components:
try: Encloses statements that may produce an exception.throw: Signals an exceptional condition and transfers control to a suitable handler.catch: Handles an exception whose type matches its parameter.
try {
if (denominator == 0)
throw denominator;
cout << numerator / denominator;
}
catch (int value) {
cout << "Division by zero is not allowed";
}When throw denominator executes, the remaining statements in the try block are skipped. The runtime searches for the nearest matching catch block. If a match is found, that handler executes. After the handler completes, execution continues after the complete try-catch structure. If no matching handler exists, the search continues through calling functions; if the exception remains unhandled, std::terminate() is called.
Describe the throwing mechanism in C++. What types of values can be thrown, and what happens after a throw expression is executed?
An exception is raised with a throw expression:
throw expression;The expression may produce a value of a built-in type, a string, or a user-defined object. User-defined exception classes are generally preferred because they can describe the error precisely.
class InvalidAge {
public:
string message;
InvalidAge(string text) : message(text) {}
};
if (age < 0)
throw InvalidAge("Age cannot be negative");After the exception is thrown:
- Normal execution at the throwing point stops.
- The thrown object is initialized from the supplied expression.
- The runtime searches for a type-compatible
catchhandler. - Local automatic objects are destroyed during stack unwinding.
- Control transfers to the first matching handler.
- If no handler is found, the program calls
std::terminate().
Exceptions should normally be thrown by value and caught by reference.
Explain the catching mechanism in C++. Discuss handler matching, handler order, and the catch-all handler.
A handler is written as catch(parameter) and is placed immediately after a try block. When an exception is thrown, handlers are examined in their written order.
try {
// Risky operation
}
catch (const DerivedError& error) {
// Handle derived exception
}
catch (const BaseError& error) {
// Handle other related exceptions
}
catch (...) {
// Handle any remaining exception
}Important rules:
- A handler normally matches an exception of the same type.
- A handler for a base-class reference can catch objects of its derived classes.
- Derived-class handlers must appear before base-class handlers; otherwise, the base handler may catch the exception first.
- Catching by
constreference avoids copying and prevents object slicing. catch (...)is the catch-all handler and can catch an exception of any type.- The catch-all handler must normally be the last handler.
Only one matching handler executes for a thrown exception.
What is stack unwinding during exception handling? Explain its role in resource management.
Stack unwinding is the process of removing active function frames from the call stack while searching for a suitable exception handler.
Suppose function main() calls f1(), which calls f2(), and f2() throws an exception. If f2() has no matching handler, its local automatic objects are destroyed and control returns toward f1(). This continues until a matching handler is found.
Importance for resource management:
- Destructors of fully constructed local objects are called automatically.
- Objects such as file wrappers, containers, and smart pointers release their resources.
- This behavior supports the RAII principle: resource acquisition is initialization.
- Raw resources that are not managed by objects may leak if cleanup depends on statements skipped by the exception.
- Throwing an exception from a destructor during stack unwinding is dangerous because a second active exception can cause
std::terminate().
Therefore, resources should be owned by automatic objects and destructors should generally not allow exceptions to escape.
What is rethrowing an exception? Explain how it is performed and identify situations in which it is useful.
Rethrowing means passing a currently handled exception to another handler at a higher level of the call stack. It is performed by writing throw; without an operand inside a catch block.
try {
processFile();
}
catch (const FileError& error) {
logError(error);
throw;
}Uses of rethrowing:
- Recording an error locally while allowing a higher layer to make the recovery decision.
- Performing partial cleanup before transferring responsibility.
- Converting exceptions at an abstraction boundary when combined with another
throwexpression. - Allowing a low-level function to report an error to user-interface or application-level code.
throw; preserves the original exception object and its dynamic type. In contrast, throw error; creates a new exception from the caught expression and may copy or slice the object. A bare throw; must only be used while an exception is being handled; otherwise, std::terminate() is called.
Design a C++ program that uses a user-defined exception class to validate a bank withdrawal. Explain the flow of exception handling.
A user-defined exception can store information about an invalid withdrawal.
#include <iostream>
#include <stdexcept>
using namespace std;
class InsufficientFunds : public runtime_error {
public:
explicit InsufficientFunds(const string& message)
: runtime_error(message) {}
};
void withdraw(double& balance, double amount) {
if (amount <= 0)
throw invalid_argument("Amount must be positive");
if (amount > balance)
throw InsufficientFunds("Withdrawal exceeds balance");
balance -= amount;
}
int main() {
double balance = 5000;
try {
withdraw(balance, 6500);
cout << "Balance: " << balance;
}
catch (const InsufficientFunds& error) {
cout << error.what();
}
catch (const invalid_argument& error) {
cout << error.what();
}
}Flow:
withdraw()validates the amount.- A nonpositive amount causes
std::invalid_argumentto be thrown. - An amount greater than the balance causes
InsufficientFundsto be thrown. - Execution of
withdraw()stops at the correspondingthrow. - The matching handler in
main()receives the exception byconstreference. - A valid withdrawal updates the balance without invoking either handler.
Deriving from std::runtime_error provides the standard what() interface.
Define a function template. Explain its syntax, instantiation, and advantages with a suitable example.
A function template defines a generic function from which the compiler can generate functions for different data types.
General syntax:
template <typename T>
return_type functionName(T parameter) {
// Function body
}Example:
template <typename T>
T maximum(T first, T second) {
return first > second ? first : second;
}
int a = maximum(10, 20); // T is int
double b = maximum(4.5, 2.1); // T is doubleWhen the compiler encounters maximum(10, 20), it deduces T as int and instantiates the required function. A type may also be supplied explicitly, such as maximum<double>(4, 5.5).
Advantages:
- Eliminates duplicate functions for different types.
- Preserves compile-time type checking.
- Improves maintainability and code reuse.
- Usually introduces no runtime polymorphism overhead.
The supplied type must support every operation used by the template; in this example, it must support comparison using >.
Explain function-template argument deduction and specialization. How are templates related to overloaded functions?
Argument deduction allows the compiler to determine template parameters from function arguments.
template <typename T>
void display(T value);
display(25); // T becomes int
display(3.14); // T becomes doubleDeduction may fail when arguments imply conflicting types. For example, a template add(T, T) cannot directly deduce one T from an int and a double. The caller may use an explicit argument such as add<double>(2, 3.5), or the template may use separate parameters.
Explicit specialization supplies special behavior for a particular type:
template <typename T>
bool equal(T a, T b) {
return a == b;
}
template <>
bool equal<const char*>(const char* a, const char* b) {
return strcmp(a, b) == 0;
}Function templates may coexist with ordinary overloaded functions. During overload resolution, the compiler considers viable ordinary functions and generated template specializations. A suitable non-template overload is generally preferred when both provide equally good conversions. Overloading is often more flexible than function-template specialization.
Define a class template and develop a generic Pair class that can store and display two values of potentially different types.
A class template is a blueprint for generating classes using one or more type or non-type parameters.
#include <iostream>
using namespace std;
template <typename T, typename U>
class Pair {
private:
T first;
U second;
public:
Pair(const T& a, const U& b) : first(a), second(b) {}
T getFirst() const {
return first;
}
U getSecond() const {
return second;
}
void display() const {
cout << first << " " << second << '\n';
}
};
int main() {
Pair<int, double> marks(101, 87.5);
Pair<string, int> student("Asha", 20);
marks.display();
student.display();
}Pair<int, double> and Pair<string, int> are distinct class types generated from the same template. The template removes the need to write separate classes for every type combination. The selected types must support operations used by member functions; display(), for example, requires stream insertion support.
Distinguish between function templates and class templates.
Function templates and class templates differ as follows:
| Basis | Function template | Class template |
|---|---|---|
| Purpose | Generates generic functions | Generates generic classes |
| Typical use | Generic operations such as searching or comparison | Generic data structures such as stacks or pairs |
| Instantiation | Usually occurs when the function is called | Occurs when a class specialization is used in a context requiring its definition |
| Argument deduction | Template arguments are commonly deduced from function arguments | Traditionally requires explicit arguments, although modern C++ supports class template argument deduction in suitable cases |
| Overloading | Can be overloaded with other templates or ordinary functions | Different templates may share a name only through specialization, not ordinary function-style overloading |
| Specialization | Supports explicit full specialization; overloading is often preferred | Supports full and partial specialization |
Example declarations are template <typename T> T square(T value); for a function template and template <typename T> class Stack; for a class template. Both provide compile-time generic programming and type safety.
Explain class templates with inheritance. Illustrate how a template class can derive from another template class.
A class template may inherit from a template base class. The derived template supplies its template arguments to the base class.
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
class Storage {
protected:
vector<T> data;
public:
void add(const T& value) {
data.push_back(value);
}
};
template <typename T>
class Stack : public Storage<T> {
public:
T pop() {
T value = this->data.back();
this->data.pop_back();
return value;
}
bool empty() const {
return this->data.empty();
}
};Stack<T> inherits the add() operation and protected data member from Storage<T>. The expression this->data is used because members inherited from a dependent base class are not always found by unqualified name lookup.
Template inheritance supports reusable relationships such as generic base containers, policies, and specialized interfaces. Each specialization, such as Stack<int>, derives from the corresponding base specialization, Storage<int>.
What is the Standard Template Library? Explain the relationship among STL containers, algorithms, and iterators.
The Standard Template Library (STL) is a major part of the C++ Standard Library that provides generic, reusable data structures and operations.
Its three central components are:
- Containers: Store and organize data. Examples include
vector,list,deque,set, andmap. - Algorithms: Perform operations such as sorting, searching, counting, copying, and reversing. Examples include
std::sort,std::find, andstd::count. - Iterators: Generalized pointer-like objects that identify positions in containers and connect containers with algorithms.
vector<int> values{4, 1, 3, 2};
sort(values.begin(), values.end());
auto position = find(values.begin(), values.end(), 3);Here, values is the container, sort and find are algorithms, and begin() and end() return iterators defining ranges. Algorithms operate on iterator ranges rather than on specific container classes, allowing one algorithm to work with many compatible containers.
Classify the main categories of STL containers and give suitable examples of each.
STL containers can be grouped into the following categories:
- Sequence containers: Store elements in a linear order controlled by the programmer. Examples are
vector,list,deque,array, andforward_list. - Ordered associative containers: Store keys in sorted order, usually using a balanced search tree. Examples are
set,multiset,map, andmultimap. - Unordered associative containers: Store elements in hash tables without maintaining sorted order. Examples are
unordered_set,unordered_multiset,unordered_map, andunordered_multimap. - Container adaptors: Provide a restricted interface over another container. Examples are
stack,queue, andpriority_queue.
Container selection depends on required operations. A vector is suitable for random access and appending, a list supports efficient insertion at a known position, a map provides sorted key-value lookup, and an unordered_map provides average constant-time key lookup.
Define an iterator. Describe the major iterator categories and the operations supported by them.
An iterator is an object that identifies an element within a container and provides a common way to traverse container elements. It behaves similarly to a pointer and commonly supports dereferencing with * and movement with ++.
Major iterator categories:
- Input iterator: Reads elements in a forward, single-pass traversal.
- Output iterator: Writes elements in a forward, single-pass traversal.
- Forward iterator: Supports repeated forward traversal and both reading and, when mutable, writing.
- Bidirectional iterator: Supports forward and backward movement using
++and--. Alistiterator is bidirectional. - Random-access iterator: Supports jumps, indexing, ordering, and arithmetic such as
iterator + n. Avectoriterator is random access. - Contiguous iterator: A modern category whose elements occupy adjacent memory locations;
vectorprovides contiguous iterators.
Algorithms state iterator requirements. For example, std::find requires input iterators, whereas std::sort requires random-access iterators and therefore cannot be used directly with std::list.
Explain how STL algorithms operate on iterator ranges. Demonstrate sorting, searching, and counting with a vector.
Most STL algorithms receive a half-open iterator range . The element identified by first is included, while the element identified by last is excluded. For a complete container, this range is commonly written as container.begin(), container.end().
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> values{5, 2, 7, 2, 1};
sort(values.begin(), values.end());
auto position = find(values.begin(), values.end(), 7);
if (position != values.end())
cout << "Found at index " << distance(values.begin(), position) << '\n';
int occurrences = count(values.begin(), values.end(), 2);
cout << "Count: " << occurrences << '\n';
}sort arranges the vector in ascending order, find returns an iterator to the first matching element or end(), and count returns the number of matches. The half-open range supports empty ranges and makes adjacent subranges easy to represent.
Describe the vector container. Discuss its storage, important member functions, complexity, and iterator invalidation rules.
std::vector is a sequence container that stores elements in contiguous memory and changes its size dynamically.
Important operations:
push_back(value)appends an element.pop_back()removes the last element.size()returns the number of elements.capacity()returns the currently allocated capacity.reserve(n)requests capacity for at least elements.at(index)performs bounds-checked access.operator[]performs unchecked indexed access.insert()anderase()modify elements at specified positions.
Complexity:
- Random access: .
- Appending: amortized .
- Insertion or deletion near the middle: because elements are shifted.
When growth exceeds capacity, reallocation moves the elements to new storage and invalidates all iterators, pointers, and references. An insertion without reallocation still generally invalidates iterators at or after the insertion point. reserve() can reduce reallocations when the expected number of elements is known.
Write and explain a C++ program that performs insertion, deletion, traversal, and sorting on a vector.
The following program demonstrates common vector operations:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> numbers{40, 10, 30};
numbers.push_back(20);
numbers.insert(numbers.begin() + 1, 50);
auto target = find(numbers.begin(), numbers.end(), 30);
if (target != numbers.end())
numbers.erase(target);
sort(numbers.begin(), numbers.end());
for (const int value : numbers)
cout << value << " ";
}Explanation:
push_back(20)inserts20at the end.insert(numbers.begin() + 1, 50)inserts50at index .find()searches for30and returns its iterator.erase(target)removes the found element.sort()orders the remaining values.- The range-based
forloop traverses the vector without changing it.
The final output is 10 20 40 50. Insertion in the middle and deletion both require shifting elements and therefore take time.
Describe the list container. Explain its structure, major operations, complexity, and limitations.
std::list is a sequence container typically implemented as a doubly linked list. Its elements are stored in separate nodes, and each node contains links to neighboring nodes.
Major operations:
push_front()andpush_back()insert at either end.pop_front()andpop_back()remove from either end.insert()anderase()modify a position identified by an iterator.remove(value)removes all elements equal to a value.sort()sorts the list using its member algorithm.merge()combines sorted lists.splice()transfers nodes between lists.
Insertion and deletion at a known position take time. Iterators and references to other elements normally remain valid after insertion or deletion. However, a list does not provide constant-time random access, operator[], or contiguous storage. Reaching the th element takes time. It also has per-node memory overhead and usually poorer cache locality than a vector.
Compare vector and list. Recommend an appropriate container for different usage scenarios and justify your choices.
| Feature | vector |
list |
|---|---|---|
| Storage | Contiguous dynamic array | Separate doubly linked nodes |
| Random access | traversal | |
| Append | Amortized | |
| Insert or erase at known middle position | due to shifting | |
| Memory overhead | Relatively low | Extra links and allocation per node |
| Cache locality | Usually high | Usually low |
| Iterator type | Random access | Bidirectional |
| General sorting | std::sort |
Member function list::sort() |
| Iterator invalidation | Reallocation may invalidate all iterators | Only erased elements normally lose validity |
Recommendations:
- Use
vectorfor indexed access, compact storage, frequent traversal, sorting, and mostly end insertions. - Use
listwhen nodes must frequently be inserted, removed, or transferred at already known iterator positions while preserving references to other elements. - A list does not automatically make arbitrary insertion fast because locating the position still takes .
vectorshould usually be the default sequence container because its compact storage and cache locality often provide better real-world performance.
Define an exception in C++. Why is exception handling preferred over traditional error-handling techniques?
Exception: An exception is an abnormal condition or runtime error that interrupts the normal flow of a program. In C++, an exception is represented by a value or object thrown by the code that detects the error.
Advantages of exception handling:
- It separates error-handling code from normal program logic.
- An error can be handled at a different level of the call stack.
- Exceptions can carry detailed information through objects.
- Errors cannot be ignored as easily as error codes.
- Different error types can be handled by different
catchblocks. - Stack unwinding automatically destroys local objects, supporting resource cleanup.
Traditional techniques such as return codes require every caller to check the returned value. Exception handling provides a structured mechanism using try, throw, and catch.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →