C++ exception handling
Exceptions are problems that occur during program execution. C++ exceptions are special situations that occur when a program is running, such as an attempt to divide by zero.
Exceptions provide a way to transfer program control. C++ exception handling involves three keywords: try, catch, and throw.
throw: When a problem occurs, the program will throw an exception. This is done using the throw keyword.
catch: Catch the exception via an exception handler at the point where you want to handle the problem. catch keyword is used to catch exceptions.
try: try The code in the block identifies the specific exception that will be activated. It is usually followed by one or more catch blocks.
If a block throws an exception, the method to catch the exception will use the try and catch keywords. Code that may throw exceptions is placed in the try block. The code in the try block is called protection code. The syntax for using try/catch statements is as follows:
try { // 保护代码 }catch( ExceptionName e1 ) { // catch 块 }catch( ExceptionName e2 ) { // catch 块 }catch( ExceptionName eN ) { // catch 块 }
If the try block will throw different exceptions in different situations, you can try to list multiple catch at this time statement, used to catch different types of exceptions.
Throw Exceptions
You can throw exceptions anywhere in a block of code using the throw statement. The operand of the throw statement can be any expression, and the type of the result of the expression determines the type of exception thrown.
The following is an example of an exception being thrown when trying to divide by zero:
double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); }
Catching the exception
catch The block follows try After the block, used to catch exceptions. You can specify the type of exception you want to catch, which is determined by the exception declaration in parentheses after the catch keyword.
try { // 保护代码 }catch( ExceptionName e ) { // 处理 ExceptionName 异常的代码 }
The above code will catch an exception of type ExceptionName. If you want the catch block to be able to handle any type of exception thrown by the try block, you must use ellipsis... inside the brackets of the exception declaration, as shown below:
try { // 保护代码 }catch(...) { // 能处理任何异常的代码 }
Here is an example, throw A divide-by-zero exception and catch the exception in a catch block.
#include <iostream> using namespace std; double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); } int main () { int x = 50; int y = 0; double z = 0; try { z = division(x, y); cout << z << endl; }catch (const char* msg) { cerr << msg << endl; } return 0; }
Since we threw an exception of type const char*, when catching the exception, we have to use const char* in the catch block. When the above code is compiled and executed, it produces the following results:
Division by zero condition!
C++ Standard Exceptions
C++ provides a series of standard exceptions, defined in<exception> ;, we can use these standard exceptions in the program. They are organized in a parent-child class hierarchy as follows:
The following table is a description of each exception that occurs in the hierarchy above:
Exception | Description |
---|---|
std::exception | The exception Is the parent class of all standard C++ exceptions. |
std::bad_alloc | This exception can be thrown by new. |
std::bad_cast | This exception can be thrown by dynamic_cast. |
std::bad_exception | This is useful when handling unexpected exceptions in C++ programs. |
std::bad_typeid | This exception can be thrown by typeid. |
std::logic_error | Exception that can theoretically be detected by reading the code. |
std::domain_error | This exception is thrown when an invalid mathematical domain is used. |
std::invalid_argument | This exception will be thrown when an invalid parameter is used. |
std::length_error | This exception is thrown when a std::string that is too long is created. |
std::out_of_range | This exception can be thrown by methods, such as std::vector and std::bitset<>::operator[]() . |
std::runtime_error | Theoretically, an exception that cannot be detected by reading the code. |
std::overflow_error | This exception is thrown when a mathematical overflow occurs. |
std::range_error | This exception is thrown when an attempt is made to store a value that is out of range. |
std::underflow_error | This exception is thrown when a mathematical underflow occurs. |
Define new exceptions
You can define new exceptions by inheriting and overloading the exception class. The following example demonstrates how to use the std::exception class to implement your own exceptions:
#include <iostream> #include <exception> using namespace std; struct MyException : public exception { const char * what () const throw () { return "C++ Exception"; } }; int main() { try { throw MyException(); } catch(MyException& e) { std::cout << "MyException caught" << std::endl; std::cout << e.what() << std::endl; } catch(std::exception& e) { //其他的错误 } }
This will produce the following results:
MyException caught C++ Exception
Here, what() Is a public method provided by the exception class, which has been overloaded by all sub-exception classes. This will return the reason for the exception.