Module 20: Exception Handling in C++
Exception Handling is a mechanism for detecting and handling runtime errors gracefully without abruptly terminating the program. Instead of crashing, exceptions allow programs to recover from errors or display meaningful error messages.
C++ provides three main keywords for exception handling:
trythrowcatch
Using exceptions helps create reliable and maintainable applications.
1. try Block
A try block contains code that might generate an exception.
Syntax
1try 2{ 3 // Code that may throw an exception 4}
Example
1#include <iostream> 2 3using namespace std; 4 5int main() 6{ 7 try 8 { 9 cout << "Executing code..." << endl; 10 } 11 catch (...) 12 { 13 cout << "Exception caught"; 14 } 15 16 return 0; 17}
Output
1Executing code...
2. throw Keyword
The throw keyword is used to generate an exception when an error occurs.
Example
1#include <iostream> 2 3using namespace std; 4 5int main() 6{ 7 int age = 15; 8 9 try 10 { 11 if (age < 18) 12 { 13 throw "You are not eligible."; 14 } 15 16 cout << "Access Granted"; 17 } 18 catch (const char* message) 19 { 20 cout << message; 21 } 22 23 return 0; 24}
Output
1You are not eligible.
3. catch Block
A catch block receives and handles the exception thrown by a try block.
Example
1#include <iostream> 2 3using namespace std; 4 5int main() 6{ 7 try 8 { 9 throw 404; 10 } 11 catch (int errorCode) 12 { 13 cout << "Error Code: " << errorCode; 14 } 15 16 return 0; 17}
Output
1Error Code: 404
4. Multiple Catch Blocks
A single try block can have multiple catch blocks to handle different types of exceptions.
Example
1#include <iostream> 2 3using namespace std; 4 5int main() 6{ 7 try 8 { 9 int choice = 2; 10 11 if (choice == 1) 12 throw 100; 13 14 if (choice == 2) 15 throw "Invalid Input"; 16 } 17 catch (int error) 18 { 19 cout << "Integer Exception: " << error; 20 } 21 catch (const char* message) 22 { 23 cout << message; 24 } 25 26 return 0; 27}
Output
1Invalid Input
5. Custom Exception
You can create your own exception classes by inheriting from std::exception.
Example
1#include <iostream> 2#include <exception> 3 4using namespace std; 5 6class InvalidAgeException : public exception 7{ 8public: 9 const char* what() const noexcept override 10 { 11 return "Age must be at least 18."; 12 } 13}; 14 15int main() 16{ 17 int age = 16; 18 19 try 20 { 21 if (age < 18) 22 { 23 throw InvalidAgeException(); 24 } 25 26 cout << "Eligible"; 27 } 28 catch (const InvalidAgeException& e) 29 { 30 cout << e.what(); 31 } 32 33 return 0; 34}
Output
1Age must be at least 18.
6. noexcept
The noexcept specifier indicates that a function is not expected to throw exceptions. If such a function throws an exception, the program calls std::terminate().
Syntax
1void functionName() noexcept;
Example
1#include <iostream> 2 3using namespace std; 4 5void display() noexcept 6{ 7 cout << "No Exception"; 8} 9 10int main() 11{ 12 display(); 13 14 return 0; 15}
Output
1No Exception
Use
noexceptfor functions that are guaranteed not to throw exceptions, especially move constructors and move assignment operators.
Complete Example
1#include <iostream> 2#include <exception> 3 4using namespace std; 5 6class DivideByZeroException : public exception 7{ 8public: 9 const char* what() const noexcept override 10 { 11 return "Division by zero is not allowed."; 12 } 13}; 14 15int main() 16{ 17 int a = 10; 18 int b = 0; 19 20 try 21 { 22 if (b == 0) 23 { 24 throw DivideByZeroException(); 25 } 26 27 cout << a / b; 28 } 29 catch (const DivideByZeroException& e) 30 { 31 cout << e.what(); 32 } 33 34 return 0; 35}
Output
1Division by zero is not allowed.
Exception Handling Flow
1Program 2 │ 3 ▼ 4try Block 5 │ 6 ▼ 7Error Occurs? 8 │ 9 ┌─┴──────────┐ 10 │ │ 11No Yes 12 │ │ 13 ▼ ▼ 14Continue throw 15 │ 16 ▼ 17 catch Block 18 │ 19 ▼ 20 Handle Exception
Standard Exception Classes
| Exception Class | Description |
|---|---|
std::exception | Base class for standard exceptions |
std::runtime_error | Runtime errors |
std::logic_error | Logical errors |
std::invalid_argument | Invalid function arguments |
std::out_of_range | Index out of range |
std::bad_alloc | Memory allocation failure |
Best Practices
- Catch exceptions by const reference.
- Throw exception objects instead of primitive types when possible.
- Keep
tryblocks as small as possible. - Use standard exception classes when appropriate.
- Use
noexceptfor functions that should never throw. - Avoid throwing exceptions from destructors.
Practice Problems
- Write a program that throws an exception for division by zero.
- Handle invalid age input using a custom exception.
- Use multiple
catchblocks to handle different exception types. - Create a custom exception for insufficient bank balance.
- Write a
noexceptfunction and explain its behavior.
Interview Questions
- What is exception handling in C++?
- What is the purpose of
try,throw, andcatch? - What happens if an exception is not caught?
- What are multiple catch blocks?
- Why should exceptions be caught by reference?
- What is a custom exception?
- What is the
what()function instd::exception? - What is the purpose of
noexcept? - Can constructors and destructors throw exceptions?
- When should you use exceptions instead of return codes?
Summary
In this module, you learned:
- What exception handling is and why it is important.
- How
try,throw, andcatchwork together. - How to use multiple
catchblocks for different exception types. - How to create and use custom exception classes.
- How
noexceptcommunicates that a function does not throw exceptions. - Best practices for writing robust, maintainable, and exception-safe C++ code.
Next Module: Module 21: Templates — Function Templates, Class Templates, Template Specialization, Variadic Templates, Non-Type Template Parameters, and Generic Programming.