Exception handling in C++

Exception handling in C++

10 mins read2.4K Views Comment
Updated on Oct 9, 2023 18:28 IST

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.

2023_01_MicrosoftTeams-image-8.jpg

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

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.

Working with Strings in C++
Working with Strings in C++
Strings in C++ is a very simple yet very important topic from exams as well as interview point of view.
Working with Strings in C++
Working with Strings in C++
Strings in C++ is a very simple yet very important topic from exams as well as interview point of view.

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;
}
Copy code

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;
}
}
Copy code

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;
}
Copy code

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
}
Copy code

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
}
Copy code

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;
}
Copy code

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 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.
Copy code

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;
}}
Copy code

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. 

About the Author

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