In C++, exception handling serves as a mechanism for managing runtime errors. It provides a way to address unforeseen and undesired circumstances that may arise while the program is running. Exception handling primarily aims to manage the regular progression of the application, even in the presence of runtime errors.
In C++, an exception serves as a runtime-triggered event indicating an error. The majority of exceptions are subclasses of the std::exception class, an integral component of the C++ Standard Library. Failing to handle an exception appropriately results in the program displaying an error message and terminating abruptly.
For Instance:
divide_by_zero = 5 / 0;
Here, the provided code raises an exception due to the impossibility of dividing a number by zero.
Syntax:
It has the following syntax:
try {
// Code that cause an exception
throw argument;
}
catch (exception) {
// code to handle the exception
}
In this particular syntax, exceptions can be triggered within the try block, with a corresponding catch block immediately following each try block. In case of an exception during execution, the throw statement will raise an exception that is then caught by the following catch block.
C++ Simple Exception Handling Example:
Let's consider an instance to demonstrate the exception handling feature in C++.
Example
#include <iostream>
using namespace std; //using standard namespace
int main() //Main Function
{
int Num, Deno; //Num(Numerator), Deno (Denominator)
cout <<"Enter the Numerator Number: ";
cin >> Num;
cout <<"Enter the Denominator Number: ";
cin >> Deno;
try {
if (Deno == 0) {
throw "Given number cannot be divided by zero!";
}
int result = Num / Deno;
cout << "The Division Result is: " << result << endl;
}
catch (const char* msg) {
cout << "Exception caught: " << msg << endl;
}
return 0;
}
Output 1:
Enter the Numerator Number: 8
Enter the Denominator Number: 0
Exception caught: Given number cannot be divided by zero!
Output 2:
Enter the Numerator Number: 20
Enter the Denominator Number: 5
The Division Result is: 4
Explanation:
In this instance, we are working with a pair of integer variables, Num (representing the Numerator) and Deno (representing the Denominator). Subsequently, the program prompts the user to input values for both the numerator and denominator. In the scenario where the denominator is 0, an exception is raised to avoid division by 0. Following this, the catch block manages the exception occurrence and presents an error message. If no errors are encountered, the program proceeds to output the result of the division.
C++ Exception Handling Keywords
In C++, we mainly used 3 keywords to perform exception handling:
- try Block
- throw Statement
- catch Block
1. try block
The try block is employed to specify the section of code that may result in an error. When an exception occurs within the try block, the program execution shifts to the catch block.
Syntax of try Block:
It has the following syntax:
try {
// Code that may cause an error
}
To Read More: Try/Catch Block
2. throw Statement
If an error occurs, we have the option to utilize the throw keyword to transmit an error message or value. This action is carried out by employing the throw keyword.
Syntax:
It has the following syntax:
throw value; // value can be a number, string, or object
3. catch Block
The catch block captures the error thrown by the throw statement. It is responsible for handling or displaying the error message. This block is executed only when an issue occurs within the try block. The catch keyword specifies the exception to be caught in the program.
Syntax:
It has the following syntax:
catch(type variable) {
// Code to handle the exception
}
Why Exception Handling is used in C++?
In C++, exception management is employed to deal with and react to unforeseen runtime errors within the program. Throughout program execution, various errors may arise, including zero division, file access issues, incorrect input, and numerous others. Neglecting exception handling could result in program termination and erratic behavior.
If exception handling is implemented, errors can be captured through the utilization of try, catch, and throw statements. This practice enhances the clarity of the code by segregating regular operations from error management procedures, ultimately enhancing the resilience, user experience, and simplifying the debugging process of the program.
C++ Exception Classes
In C++, predefined exceptions are defined within the standard exception hierarchy class, which we can make use of in our software. The diagram below illustrates the organization of the parent-child class structure:
All C++ exception classes inherit from the std::exception class. Next, we will explore a compilation of frequently encountered C++ exception classes.
| Exception | Description |
|---|---|
| std::exception | It is an exception and parent class of all standard C++ exceptions. |
| std::logic_error | It is an exception that can be detected by reading a code. |
| std::runtime_error | It is an exception that cannot be detected by reading a code. |
| std::bad_exception | It is used to handle the unexpected exceptions in a c++ program. |
| std::bad_cast | This exception is generally thrown bydynamic_cast. |
| std::bad_typeid | This exception is generally thrown bytypeid. |
| std::bad_alloc | This exception is generally thrown bynew. |
Throwing Exceptions:
In C++, exceptions are triggered using the throw keyword. Upon an exception being thrown within the program, the regular flow of the program halts, and the control transfers to the closest catch block capable of managing the exception. In the absence of a catch block within the code, the program will come to an end.
An exception can represent any legitimate C++ object, although it is common to throw instances of standard exception classes or custom-defined exceptions.
Throwing Exception Example:
Let's consider an example to demonstrate how exceptions are thrown in C++.
Example
#include <iostream>
using namespace std; //using standard namespace
void divide(int a, int b) {
if (b == 0) {
throw runtime_error("Division by zero is not allowed!");
}
cout << "Result: " << a / b << endl;
}
int main() //Main Function
{
try {
divide(10, 0); // It will throw an exception
} catch (const exception& e) {
cout << "Caught an exception: " << e.what() << endl; //prints an output
}
return 0;
}
Output:
Caught an exception: Division by zero is not allowed!
Explanation:
In this instance, the divide method accepts a pair of integers and validates whether the second integer is zero. If the condition b == 0 is true, an error is triggered by invoking throw runtime_error("message"). The primary function invokes divide(10, 0), leading to an error being raised. The catch block intercepted the error and displayed an error message.
Catching Exceptions
In C++, the catch block is employed to capture an exception in the program. A catch block comes after a try block and specifies the category of exception it manages. Multiple catch blocks can be used to address various types of exceptions.
Catching Exception Example:
Let's consider a scenario to demonstrate handling exceptions in C++.
Example
#include <iostream>
using namespace std; //using standard namespace
void testFunction(int x) {
try {
if (x < 0)
throw "Negative Number Exception";
else if (x == 0)
throw 0;
else
throw 3.14;
} catch (const char* msg) {
cout << "Caught an exception: " << msg << endl;
} catch (int num) {
cout << "Caught an integer exception: " << num << endl;
} catch (...) {
cout << "Caught an unknown exception" << endl;
}
}
int main() //Main Function
{
testFunction(-5); // Catches char* exception
testFunction(0); // Catches int exception
testFunction(20); // Catches default exception
return 0;
}
Output:
Caught an exception: Negative Number Exception
Caught an integer exception: 0
Caught an unknown exception
Explanation
In this instance, the testFunction function encompasses a try block in which diverse categories of exceptions are raised. Subsequently, the main function invokes testFunction with varying inputs to elicit a range of exceptions.
Defining New Exceptions:
C++ permits the development of custom exception classes derived from std::exception. This functionality enhances the structuring and management of various error categories.
Demonstrating New Exceptions Example:
Example
#include <iostream>
#include <exception>
using namespace std; //using standard namespace
class MyException : public exception {
public:
const char* what() const noexcept override {
return "Custom Exception Occurred";
}
};
void test() {
throw MyException(); // Throwing custom exception
}
int main() //Main Function
{
try {
test();
} catch (const MyException& e) {
cout << "Caught custom exception: " << e.what() << endl;
}
return 0;
}
Output:
Caught custom exception: Custom Exception Occurred
Explanation:
In this illustration, a personalized exception class named MyException is declared, inheriting from std::exception. Following this, the what method is redefined to provide a customized error statement. The function test raises a MyException. The primary function captures the exception and displays the error message.
Using Multiple Catch Blocks Example:
Let's consider a scenario to demonstrate the usage of multiple catch blocks in C++.
Example
#include <iostream>
using namespace std; //using standard namespace
int main() //Main Function
{
int age;
try {
cout << "Enter your age: ";
cin >> age;
if (age < 0) {
throw "NegativeAge"; // throw string for negative age
}
if (age > 120) {
throw age; // if the age is too high, throw the age itself
}
cout << "Your age is: " << age << endl;
}
catch (const char* msg) {
cout << "Error: Age cannot be negative." << endl;
}
catch (int highAge) {
cout << "Error: Age seems too high (" << highAge << ") - please enter a real age." << endl;
}
return 0;
}
Output:
Case 1 (Valid age):
Enter your age: 30
Your age is: 30
Case 2 (Negative age):
Enter your age: -10
Error: Age cannot be negative.
Case 3 (Too high age):
Enter your age: 200
Error: Age seems too high (200) - please enter a real age.
C++ Exception Handling MCQs
- Which one of the following keywords is used to catch exceptions in C++?
- throw
- catch
- finally
- Which one of the following statements is correct about exception handling in C++?
- Only one catch is allowed in the program.
- Try block must be followed by at least one catch block.
- Onl built-in exceptions may be caught.
- Exception handling should be utilized in every program.
- Which one of the following options is the base class for all standard exceptions in C++?
- exception
- runtime_error
- erro_base
- logic_error
- What is the main goal of the exception handling in C++?
- Is used to handle syntax errors.
- Is used to maintain logical errors
- Is used to maintain compilation errors
- Is used to handle runtime errors.
- Which one of the following standard header files is needed for exception handling in C++?
- <try>
- <exception>
- <error>
- <stdexcept>