Exception handling in C++
Exception handling in C++ provides a way to deal with unexpected situations such as run-time errors. In this we have covered Exception handling in C++with programming explanation with code explanation.In this different types of exception handlin is also covered.
C++ supports several ways of handling errors and exceptions in your programs. These include direct access to the standard library, virtual functions, destructors, memory management, and overloads. The standard library provides a consistent set of functions for handling exceptions. You can also register your own exceptions with the compiler using catch-all codes, allowing you to define exceptions for specific situations. For example, you could define an exception for when an image doesn’t load correctly or when the file is not found.
Table of contents
Best-suited C++ courses for you
Learn C++ with these high-rated online courses
What is an exception?
An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. Exceptions are typically used to indicate an error has occurred and to transfer control to a specific location in the code where the error can be handled.
The main benefit of using exceptions is that it allows you to separate the error handling code from the normal code, making it more readable and maintainable. The exception-handling code can be kept separate from the rest of the code and can be reused easily across the program.
Also read: Default Arguments in C++
What is exception handling?
In C++, exception handling is a mechanism to handle runtime errors. It allows the program to transfer control to a special block of code, called an exception handler when an exceptional condition (such as a divide-by-zero error) occurs. This allows the program to recover gracefully from the error rather than terminating abruptly.
The try block encloses the code that might throw an exception. The program will jump to the associated exception handler if an exception is thrown within the try block. The exception handler is defined using the catch block, which is placed immediately after the try block. The catch block takes an argument that specifies the type of exception it can handle.
Understand the need for this concept in real-life situations
Suppose there is a form that is to be filled by the user, and the form there is a field called age. This field should contain integers value only, but what if the user enters a character value in it? In that case, the user will get an error. He gets this error because the programmer has done exception handling in the code while making that form. This is where exception handling is used.
So we have to consider all scenarios because users can also enter any invalid value. Our program should be able to respond to that type of invalid value scenarios.
What if we don’t know which exception to throw?
It is important to note that the std::exception class is a base class for all the standard exceptions. When the exception that is thrown is not of type std::exception, the catch block will not catch it, so you can catch the specific type of exception or use catch(…) to catch all types of exceptions.
Preparing for a C++ interview? Check out the Top C++ Interview Questions and Answers
Also Read – Understanding Operators in C++
Learn more: Basics of C Programming Language
Related Read – Binary Search in C++
C++ Exception Handling Keywords
1. try
The try block contains the code that may throw an exception. If an exception is thrown within the try block, the control is transferred to the corresponding catch block.
2. catch
The catch block contains the code that will handle the exception. Each catch block is associated with a specific exception type, and the catch block that corresponds to the type of exception that was thrown will be executed. If the catch block does not have a matching exception type, the exception is passed to the next catch block.
3. throw
The throw keyword is used to throw an exception. The expression that follows the throw keyword is used to create the exception object. The exception object is then passed to the nearest catch block that can handle it.
Explore:C++ Online Courses & Certifications
Types of exceptions
1. Standard exceptions
These exceptions are a part of the C++ Standard Library and are defined in the <exception> header. They are intended to provide a standard set of exception classes for use in C++ programs and are designed to represent a wide range of error conditions that may occur during the execution of a program. The standard exceptions include std::logic_error, which represents errors resulting from an application’s logic (e.g., an invalid argument passed to a function), and std::runtime_error, which represents errors that occur due to external factors (e.g., a file not found).
2. Derived exceptions
These exceptions are derived from standard exceptions. They provide a more specific indication of the type of error. For example, std::out_of_range is derived from std::logic_error and is used to indicate that an index or a value is out of the acceptable range for a container or an algorithm.
3. User-defined exceptions
The user in the application code defines these exceptions. They can be derived from standard exceptions or a user-defined base class. User-defined exceptions allow the programmer to indicate errors specific to the application rather than relying on standard exceptions.
C++ Standard Exceptions
1. std::Exception
Exceptions and superclasses of all standard C++ exceptions.
2. std::bad_alloc
When the new operator fails to allocate the requested space.
3. std::bad_cast
It can be cast by dynamic_cast.
4. std::bad_exception
This is a convenient device for handling unexpected exceptions in C++ programs.
5. std::bad_typeid
This can be thrown by typeid.
6. std::logic_error
Exceptions that can theoretically be detected by reading the code.
7. std::domain_error
This is the exception thrown when a mathematically invalid domain is used.
8. std::length_error
This is triggered when a std::string that is too large is created.
9. std::out_of_range
This can be thrown through ‘at’ methods such as std::vector and std::bitset<>::operator[]().
10. std::invalid_argument
This is thrown due to invalid arguments.
11. std::runtime_error
An exception that cannot be detected in principle by reading the code.
12. std::range_error
This happens when you try to store an out-of-range value.
13. std::underflow_error
This is triggered when a math underflow occurs.
14. std::overflow_error
This is triggered when math overflow occurs.
Throwing Exceptions in C++
In C++, exceptions are thrown using the “throw” keyword, followed by an expression that evaluates to the exception object.
Here’s an example of throwing an exception when a function is called with an invalid argument:
#include <iostream>#include <stdexcept>
int divide(int a, int b) { if (b == 0) { throw std::invalid_argument("division by zero"); } return a / b;}
int main() { try { int result = divide(1, 0); std::cout << result << std::endl; } catch (const std::invalid_argument& e) { std::cout << "An exception occurred: " << e.what() << std::endl; } return 0;}
Output:
An exception occurred: division by zero
In this example, the divide function throws an exception of type std::invalid_argument if the second argument is zero. The exception is caught in the catch block in the main, and the message “An exception occurred: division by zero” is printed.
You can throw different types of exceptions as well like built-in types and custom types.
#include <iostream>#include <stdexcept>using namespace std;
int x = 5;
int main() {try { if (x == 0) throw x; else if (x > 0) throw 'x'; else throw "x is negative";}catch (int i) { cout << "Caught an int exception: " << i << endl;}catch (char c) { cout << "Caught a char exception: " << c << endl;}catch (char* str) { cout << "Caught a string exception: " << str << endl;}}
Output:
Caught a char exception: x
In this example, the code throws an exception based on the value of x: if x is zero, it throws an int exception, if x is positive it throws a char exception, otherwise it throws a string exception. The catch blocks catch the exception and print an appropriate message.
It’s important to note that throwing an exception can cause the program to jump out of multiple levels of function calls, making sure all the resources are freed and keeping the program in a consistent state.
By now, you must have a proper understanding about C++. If not, we recommend you read the difference between C and C++.
Catching Exceptions in C++
In C++, exceptions are caught using a catch block. A catch block consists of the keyword “catch” followed by parentheses containing a variable that will be initialized with the exception object. The variable is typically of a type that is derived from the std::exception class.
Here’s an example of catching an exception:
try {
// code that might throw an exception
} catch (exceptionType e) {
// exception handling code
}
If an exception is thrown, the program looks for the nearest catch block that can handle the exception, based on the type of exception thrown and the types of exceptions handled in the catch blocks.
For example:
try { int result = divide(1, 0); std::cout << result << std::endl;} catch (const std::invalid_argument& e) { std::cout << "An exception occurred: " << e.what() << std::endl;}
In this example, the call to divide might throw an exception of type std::invalid_argument. The catch block catches the exception and prints the message “An exception occurred: division by zero”.C++ allows you to catch multiple types of exceptions in one catch block using the following syntax:
try { // code that might throw an exception} catch (exceptionType1 e1) { // exception handling code for exceptionType1} catch (exceptionType2 e2) { // exception handling code for exceptionType2}
It’s also possible to catch all exceptions with a catch-all block. It is done by catch block without any argument.
try { // code that might throw an exception} catch (...) { // code to handle any exception}
The catch-all block will catch any exception that is not caught by the previous catch block. It’s typically used as a last resort, because it makes it harder to determine what went wrong when an exception occurs.
It’s important to remember that if an exception is thrown, it must be caught at some point, otherwise the program will terminate.
Examples of exception handling
Example 1: Divide by zero
try { int x = 0; int y = 5 / x; // this will throw a divide-by-zero exception} catch (std::exception& e) { std::cout << "Error: " << e.what() << std::endl;}
Output:
Please enter the age
122
Access denied- You must not enter a valid value.
Program finished with exit code 0
Press ENTER to exit console.
Code explanation
This is C++ code for a simple program that prompts the user to enter their age and then checks if the age is a valid number between 0 and 100. If the age is not within this range, an exception is thrown, which is caught by the catch block, which prints an error message.
It uses a try-catch block to check for the exception, which is thrown when the age entered is less than 0 or greater than 100.
Code explanation
The code attempts to divide 5 by x, where x is equal to zero. Dividing by zero is undefined and therefore generates a divide-by-zero exception.
The exception object is passed as a reference to the catch block and can be used to get more information about the exception. In this example, the what() member function is called on the exception object to print a message describing the error. The message printed is “Error: std::exception”.
Example 2:Enter the age
#include <iostream>using namespace std; int main() { try { std::cout<<"Please enter the age"<<std::endl; int age=0; std::cin>>age; if (age<0 || age>100) { throw (age);} } catch (int e) {cout << "Access denied - You must enter a valid age.\n";} return 0;}Output:Please enter the age122Access denied- You must not enter a valid value.Program finished with exit code 0Press ENTER to exit console.Code explanationThis is C++ code for a simple program that prompts the user to enter their age and then checks if the age is a valid number between 0 and 100. If the age is not within this range, an exception is thrown, which is caught by the catch block, which prints an error message.It uses a try-catch block to check for the exception, which is thrown when the age entered is less than 0 or greater than 100.
Example 3:Multiple catch
#include <iostream>#include<exception>using namespace std;int main() { try { std::cout<<"Please enter the age"<<std::endl; int age=0; std::cin>>age; if (age<0 || age>100) { throw 'a'; } } catch (int e) { std::cout << "Access denied - You must enter a valid age."<<e<<std::endl; } catch (char e) { std::cout << "Access denied - You must not enter a char value."<<e<<std::endl; } catch (...) { std::cout << "Access denied - You must not enter a char value."<<std::endl; }}
Output:
Please enter the age
122
Access denied- You must not enter a valid value.
Program finished with exit code 0
Press ENTER to exit console.
Code explanation
This is C++ code for a simple program that prompts the user to enter their age and then checks if the age is a valid number between 0 and 100. If the age is not within this range, an exception is thrown, which is caught by the catch block, which prints an error message.
It uses a try-catch block to check for the exception, which is thrown when the age entered is less than 0 or greater than 100.
Output
Please enter the age
Kl
Access denied- You must not enter a char value.
Program finished with exit code 0
Press ENTER to exit console.
Code explanation
This code is similar to the previous one, but it has catch blocks for different exceptions. It would catch an int exception in the first catch block, a char exception in the second catch block, and any other type of exception in the third catch block, which uses ‘…’ as the argument.
In this case, the exception is thrown as ‘a’ (a char). If the input is a char or any other type than int, it will catch that exception in the second catch block, which would print the error message, “Access denied – You must not enter a char value.”
The third catch block with ‘…’ is called the catch-all block. It’s a generic catch block that catches any exception that is not caught by the previous catch block.
Conclusion
It is essential to handle the exception properly, and it should not cause the program to crash or have undefined behavior. The program should not continue its normal flow after the exception is thrown.
Exception specifications are a way to tell the compiler which exceptions a function may throw. This can be done by including a throw specification at the end of the function declaration, which lists the types of exceptions the function may throw. However, exception specifications are considered deprecated in C++11 and later versions and should be avoided.
This is a collection of insightful articles from domain experts in the fields of Cloud Computing, DevOps, AWS, Data Science, Machine Learning, AI, and Natural Language Processing. The range of topics caters to upski... Read Full Bio