Exception handling is very crucial in C++. It provides a mechanism for managing and responding to runtime errors. Instead of allowing errors to crash the program or lead to unpredictable behavior, exception handling allows you to detect, handle, and recover from errors. It helps to improve the stability and user experience of our applications. In this blog, we will discuss about Exception Handling in C++.
A C++ exception is an object that represents an error or unexpected condition during program execution. It is thrown using the throw keyword and caught using try and catch blocks. This allows the program to handle errors gracefully, preventing crashes and enabling proper error management.
Here's your problem of the day
Solving this problem will increase your chance to get selected in this company
Skill covered: C++
What is polymorphism in C++?
Classes treated as one through inheritanceCreation of multiple classesReturning multiple values
Choose another skill to practice
Types of Exceptions in C++
There are two types of Exceptions in C++
Synchronous Exceptions: These occur during the execution of a specific code statement, such as invalid operations like division by zero or accessing invalid memory. They are directly related to the code that caused them.
Asynchronous Exceptions: These are triggered by external events or conditions, such as hardware interrupts or signals, rather than by specific code statements. They can occur independently of the program’s current execution flow.
Why do we need Exception Handling in C++?
Graceful Error Management: Exception handling allows the program to manage unexpected errors without crashing, ensuring a smooth user experience.
Improved Code Readability: Using try and catch blocks makes it easier to understand and maintain error handling logic.
Separation of Concerns: It helps separate normal program logic from error-handling code, making the application cleaner.
Robust Applications: Exception handling makes programs more reliable by catching and addressing runtime errors efficiently.
Resource Management: Proper handling prevents memory leaks by ensuring resources are released even when errors occur.
Exception Handling keywords in C++
These are three keywords that are used to resolve exceptions in C++.
1. Try in C++
A try block encloses code that may throw exceptions. It allows you to define a section of code where errors might occur and provides a mechanism to handle those errors using catch blocks.
2. Catch in C++
A catch block follows a try block and handles exceptions thrown within it. It specifies the type of exception it can handle and contains code to manage the error, preventing program termination.
3. Throw in C++
The throw keyword is used to signal the occurrence of an exception. It transfers control to the nearest catch block that matches the type of the thrown exception, enabling error handling.
There is one try statement in the above syntax and many catch statements. The Exception_name is the name of the exception to be caught. The exception_1,exception_2, and exception_N are defined names. They are referring to the exceptions.
Why is Exception Handling used in C++?
The main advantages of exception handling over traditional error handling are given below.
To distinguish the error handling code from the normal code: In traditional error handling, we always use if and else statements to handle the errors. These traditional error handling codes get mixed up with the normal code. This makes code less readable and maintainable. We use exception handling over traditional error handling to get rid of these problems.
A function can handle any exception they choose: In C++, a function can identify the exceptions that it throws with the help of the throw keyword. The caller of this function will handle the uncaught exception either by specifying it again or catching it.
Grouping of Error Types: We use exception handling to create a hierarchy of exception objects, group exceptions in namespaces or classes, categorize them according to types.o
Example of Exception Handling in C++
C++
C++
#include<bits/stdc++.h> using namespace std; int main() { try { int age=16; int voting_age=18; if (age>=voting_age) { cout<< "You are eligible for voting."; } else { throw "You are not eligible for voting."; } } catch (const char* msg) { cout<< "For voting, You must be at least 18 years old." <<endl; cout<<msg; } return 0; }
You can also try this code with Online C++ Compiler
All the standard exceptions are defined in the <exception> class. These are described below:
Exception
Description
std::bad_exception
It is used for handling unexpected exceptions in C++ programs.
std::exception
An exception and parent class of all the standard exceptions of C++.
std::bad_alloc
This exception occurs when the new operator fails to allocate the requested space.
std::domain_error
This is an exception that is thrown when a mathematically invalid domain is used.
std::bad_typeid
This is an exception thrown by typeid.
std::bad_cast
This exception is thrown by dynamic_cast.
std::invalid_argument
This is an exception thrown for using invalid arguments.
std::length_error
This is an exception thrown after creating a big std::string.
std::out_of_range
This exception is thrown by the 'at' method.
std::logic_error
This is the type of exception that theoretically can be detected by reading the code.
std::overflow_error
This is an exception that is thrown after the occurrence of a mathematical overflow.
std::range_error
This is an exception that is thrown when you attempt to store an out-of-range value.
std::runtime_error
This is the type of exception that cannot be detected via reading the code.
std::underflow_error
This is an exception thrown after the occurrence of mathematical underflow.
User-defined Exceptions in C++
Users can define their own exceptions by inheriting and overriding the exception class functionality. the given example shows how you can use std::exception class to implement your own exception in the standard way-
C++
C++
#include<bits/stdc++.h> #include<exception> using namespace std; class Divisor_zero_exception: public exception { public: const char *what()const throw() { return "The divisor can not be zero."; } }; int main() { try { int a=15; int b=0; if (b == 0) { Divisor_zero_exception e; throw e; } else { cout<<"the value of a/b="<<a/b<<endl; } } catch(exception& ex) { cout << ex.what()<<endl; } return 0; }
You can also try this code with Online C++ Compiler
Performance Overhead: Using exceptions can impact performance due to the extra overhead in maintaining and handling them.
Complexity: Overuse of exceptions can make the code more complex and harder to follow.
Unintended Flow Changes: If exceptions are not handled carefully, they can disrupt the normal flow of the program, making debugging harder.
Platform Dependency: Exception handling mechanisms may vary slightly across different platforms or compilers, affecting portability.
Advantages of Exception Handling
Error Propagation: Exceptions allow errors to be propagated up the call stack, making error handling more centralized and organized.
Cleaner Code: It separates error-handling code from regular code, improving code readability and maintainability.
Automatic Resource Management: Exception handling ensures that resources such as memory, files, and network connections are properly released even in case of an error.
Robustness: It makes the program more reliable by catching unexpected errors at runtime and handling them appropriately.
Disadvantages of Exception Handling
Performance Impact: Exception handling can slow down program execution due to the overhead of managing exceptions.
Code Complexity: Misuse or overuse of exceptions can lead to complex code, making it harder to debug and maintain.
Difficulty in Understanding Flow: Since exceptions can change the normal control flow, tracking down issues in a program becomes more difficult.
Not Always Necessary: In some cases, simple error-handling mechanisms, like return codes, may be sufficient and easier to implement.
Frequently asked questions
What are the principles of exception handling in C++?
The principles of exception handling in C++ include separating error-handling code from regular code using try and catch blocks, using the throw keyword to signal errors, and ensuring that exceptions are caught and handled properly to maintain program stability and reliability.
Can a try block be nested under another try block?
Yes, a try block can be nested within another try block. This allows for more granular exception handling, where different levels of code can handle exceptions separately. Each nested try block can have its own corresponding catch blocks to manage specific errors.
​​What are the limitations of exception handling in C++?
Limitations of exception handling in C++ include potential performance overhead, complexity in managing multiple exceptions, and the need for careful design to avoid unhandled exceptions. Additionally, exceptions can't be used for flow control and require proper cleanup of resources to prevent leaks.
Conclusion
In this article, we have discussed Exception Handling in C++. It is a powerful feature that enhances the robustness and reliability of your programs by allowing graceful error management. By using try, catch, and throw, you can handle runtime errors effectively and maintain clean, readable code.