C++ | C + + exception handling

C++ | C + + exception handling

C + + exception handling

Exceptions are problems that occur during program execution. C + + exceptions are special cases that occur when a program is running, such as an attempt to divide by zero.

Exceptions provide a way to transfer control of the program. C + + exception handling involves three keywords: try, catch and throw.

  • Throw: when a problem occurs, the program throws an exception. This is done by using the throw keyword.
  • Catch: catch exceptions through the exception handler where you want to handle the problem. The catch keyword is used to catch exceptions.
  • Try: the code in the try 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 that catches the exception will use the try and catch keywords.
The code that may throw an exception is placed in the try block. The code in the try block is called protection code. The syntax for using the try/catch statement is as follows:

try
{
   // Protection code
}catch( ExceptionName e1 )
{
   // catch block
}catch( ExceptionName e2 )
{
   // catch block
}catch( ExceptionName eN )
{
   // catch block
}

If the try block throws different exceptions in different situations, you can try to list multiple catch statements to catch different types of exceptions.

Throw exception

You can use the throw statement to throw an exception anywhere in the code block.
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.

Example 1:

/*******************************************************************
 *   > File Name: throw.cpp
 *   > Create Time: 2021 September 13, 2009 9:08:11
 ******************************************************************/
#include <iostream>
using namespace std;

double division(int a, int b)
{
    if (b == 0) /* An exception was thrown when trying to divide by zero */
    {
        throw "Division by zero condition!";
        return (-1);
    }

    return (a/b);
}

int main(void)
{
    division(8, 0);
    return 0;
}

Compile and run:

PS E:\fly-prj\cplusplus\day11> make 
g++ -o throw throw.cpp -g -Wall
PS E:\fly-prj\cplusplus\day11> .\throw.exe
terminate called after throwing an instance of 'char const*'
      0 [main] throw 1869 cygwin_exception::open_stackdumpfile: Dumping stack trace to throw.exe.stackdump

Catch exception

The catch block follows the try block 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
{
   // Protection code
}catch( ExceptionName e )
{
  // Code to handle exception name
}

The above code will catch an exception of type ExceptionName.
If you want the catch block to handle any type of exception thrown by the try block, you must use an ellipsis... Within the parentheses of the exception declaration, as follows:

try
{
   // Protection code
}catch(...)
{
  // Code that can handle any exception
}

Example 2:

/*******************************************************************
 *   > File Name: try-catch.cpp
 *   > Create Time: 2021 September 13, 2009 9:24:33
 ******************************************************************/
#include <iostream>
using namespace std;

double division(int a, int b)
{
    if (b == 0)
    {
        throw "Division by zero condition!";
        return (-1);
    }

    return (a/b);
}

int main(void)
{
    int x = 50;
    int y = 0;
    double d = 0.0;

    try
    {
        d = division(x, y);
        cout << "d = " << d << endl;
    }
    catch(const char *msg)
    {
        cerr << msg << endl;
    }

    return 0;
}

Compile and run:

## An exception of type const char * was thrown, so when the exception is caught, const char * must be used in the catch block.
PS E:\fly-prj\cplusplus\day11> make 
g++ -o try-catch try-catch.cpp -g -Wall
PS E:\fly-prj\cplusplus\day11> .\try-catch.exe
Division by zero condition!

Exceptions to the C + + standard

The following table describes each exception in the above hierarchy:

abnormaldescribe
std::exceptionThis exception is the parent of all standard C + + exceptions.
std::bad_allocThis exception can be thrown through new.
std::bad_castThe exception can be passed through dynamic_cast throw.
std::bad_exceptionThis is useful when dealing with unexpected exceptions in C + + programs.
std::bad_typeidThis exception can be thrown through typeid.
std::logic_errorIn theory, exceptions can be detected by reading the code.
std::domain_errorThis exception is thrown when an invalid mathematical field is used.
std::invalid_argumentThis exception is thrown when an invalid parameter is used.
std::length_errorThis exception is thrown when too long std::string is created.
std::out_of_rangeThis exception can be thrown through methods, such as std::vector and STD:: BitSet < >:: operator .
std::runtime_errorExceptions that cannot theoretically be detected by reading code.
std::overflow_errorThis exception is thrown when a math overflow occurs.
std::range_errorThis exception is thrown when an attempt is made to store a value that is out of range.
std::underflow_errorThis exception is thrown when a mathematical underflow occurs.

Define a new exception

You can define new exceptions by inheriting and overloading the exception class.

Example 2:

/*******************************************************************
 *   > File Name: classException.cpp
 *   > Create Time: 2021 September 13, 2008 18:56:53
 ******************************************************************/
#include <iostream>
#include <exception>
using namespace std;

struct MyException : public exception
{
    // what() is a public method provided by the exception class, which has been overloaded by all sub exception classes.
    // This returns the cause of the exception.
    const char * what() const throw()
    {
        return "C++ Exception";
    }
};

int main(void)
{
    try
    {
        throw MyException();
    }
    catch(MyException& e)
    {
        std::cout << "MyException caught" << std::endl;
        std::cout << e.what() << std::endl;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }
    
    return 0;
}

Compile and run:

PS E:\fly-prj\cplusplus\day11> make
g++ -o classException classException.cpp -g -Wall
PS E:\fly-prj\cplusplus\day11> .\classException.exe
MyException caught
C++ Exception

Example 3:

/*******************************************************************
 *   > File Name: classException1.cpp
 *   > Create Time: 2021 September 13, 2014 19:14:54
 ******************************************************************/
#include <iostream>
#include <string>
#include <exception>
using namespace std;

int main(void)
{
    string str = "http://c.biancheng.net";

    try
    {
        char ch1 = str[100];
        cout << ch1 << endl;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
        std::cout << "[1]out of bound!" << endl;
    }

    try
    {
        char ch2 = str.at(100);
        cout << ch2 << endl;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
        std::cout << "[2]out of bound!" << endl;
    }

    return 0;
}

Compile and run:

PS E:\fly-prj\cplusplus\day11> make
g++ -o classException1 classException1.cpp -g -Wall
PS E:\fly-prj\cplusplus\day11> .\classException1.exe

basic_string::at: __n (which is 100) >= this->size() (which is 22)
[2]out of bound!

It can be seen that the first try does not catch an exception and outputs a meaningless character (garbage value). Because [] does not check that the subscript is out of bounds and does not throw an exception, try cannot detect any errors. In other words, when an exception occurs, the exception must be explicitly thrown before try can detect it; If it is not thrown out, even if there is an exception, try cannot detect it. The so-called throwing an exception is to clearly tell the program what error has occurred.

The second try detects an exception and sends it to catch to execute the statements in catch. It should be noted that once an exception is thrown, it will be immediately detected by try, and the statements after the exception point (the location of the exception) will not be executed. In this example, the position where the exception is thrown is the at() function, and the cout statement behind it will not be executed again, so its output cannot be seen.

To put it bluntly, after an exception is detected, the execution flow of the program will jump from the exception point to the location of the catch, and the statements behind the exception point and in the current try block will not be executed again; Even if the catch statement successfully handles the error, the execution flow of the program will not fall back to the exception point, so these statements will never have a chance to execute.

After executing the code contained in the catch block, the program will continue to execute the code behind the catch block and resume the normal execution flow.

Exception handling process:

Throw( Throw)--> Detection( Try) --> Capture( Catch)

Example 4:

/*******************************************************************
 *   > File Name: classExceptionFunc.cpp
 *   > Create Time: 2021 September 13, 2009 19:26:53
 ******************************************************************/
#include <iostream>
#include <string>
#include <exception>
using namespace std;

void func(){
    /*  try An exception occurred in a function called in the block. */
    throw "Unkown Exception";
    cout << "[1] This statement will not be executed." << endl;
}

int main(void)
{
    try
    {
        func();
        cout << "[2] This statement will not be executed." << endl;
    }
    catch(const char* &e)
    {
        std::cerr << e << '\n';
        cout << "[3] This statement will be executed." << endl;
    }
    
    return 0;
}

Compile and run:

PS E:\fly-prj\cplusplus\day11> make 
g++ -o classExceptionFunc classExceptionFunc.cpp -g -Wall
PS E:\fly-prj\cplusplus\day11> .\classExceptionFunc.exe
Unkown Exception
[3] This statement will be executed.

Example 5:

/*******************************************************************
 *   > File Name: classExceptionFunc1.cpp
 *   > Create Time: 2021 September 13, 2009 19:34:17
 ******************************************************************/
#include <iostream>
#include <string>
#include <exception>
using namespace std;

/*
try A function is called in the block, and the function calls another function. The other function throws an exception:
*/
void func_inner()
{
    throw "Unkown Exception";
    cout << "[1]This statement will not be executed." << endl;
}

void func_outer()
{
    func_inner();
    cout << "[2]This statement will not be executed." << endl;
}

int main(void)
{
    try
    {
        func_outer();
        cout << "[3]This statement will not be executed." <<endl;
    }
    catch(const char* &e)
    {
        std::cerr << e << '\n';
        cout << "[4]This statement will be executed." << endl;
    }

    return 0;
}

Compile and run:

PS E:\fly-prj\cplusplus\day11> make
g++ -o classExceptionFunc1 classExceptionFunc1.cpp -g -Wall
PS E:\fly-prj\cplusplus\day11> .\classExceptionFunc1.exe  
Unkown Exception
[4]This statement will be executed.

Type conversion of catch in matching process

There are various type conversions in C/C + +. Take an ordinary function (non template function) as an example. When a function call occurs, if the types of the argument and the formal parameter are not strictly matched, the type of the argument will be properly converted to adapt to the type of the formal parameter. These conversions include:

  • Arithmetic conversion: for example, int to float, char to int, double to int, etc.
  • Upward Transformation: that is, the transformation from derived class to base class. Please click< C + + upward transformation (assigning derived classes to base classes) >Learn more.
  • Const conversion: that is, convert non const types to const types, for example, convert char * to const char *.
  • Array or function pointer conversion: if the function parameter is not a reference type, the array name will be converted to an array pointer, and the function name will also be converted to a function pointer.
  • User defined type conversion.

Catch also performs type conversion in the process of matching exception types, but this conversion is more limited. It can only perform "up conversion", "const conversion" and "array or function pointer conversion". The rest cannot be applied to catch.

Example 6:

/*******************************************************************
 *   > File Name: classExceptionConst.cpp
 *   > Create Time: 2021 September 13, 2014 19:46:04
 ******************************************************************/
#include <iostream>
using namespace std;

int main(void)
{
    int nums[] = {1, 2, 3};
    try
    {
        throw nums;
        cout << "This statement will not be executed." << endl;
    }
    catch(const int*  &e) /* Citation is to improve efficiency. If you don't use references, you have to go through the process of object copy (calling the copy constructor). */
    {
        std::cerr << "Exception type: const int * " << e << '\n';
    }
    
    return 0;
}

Compile and run:

PS E:\fly-prj\cplusplus\day11> make 
g++ -o classExceptionConst classExceptionConst.cpp -g -Wall
PS E:\fly-prj\cplusplus\day11> .\classExceptionConst.exe
Exception type: const int * 0xffffcbd4

The original type of num is int [3], but there is no strictly matching type in catch, so it is converted to int * first and then const int *.

Array is also a type. Array is not equivalent to pointer, which has been explained in< Array and pointer are by no means equivalent. Array is another type >And< When exactly will arrays be converted to pointers >It is explained in detail in.

Detailed explanation of C++ throw

Detailed explanation of C++ throw

C++ exception class: the base class of C + + standard exception

C++ exception class: the base class of C + + standard exception

The exception class is located in the header file and is declared as:

class exception{
public:
    exception () throw();  //Constructor
    exception (const exception&) throw();  //copy constructor 
    exception& operator= (const exception&) throw();  //Operator overloading 
    virtual ~exception() throw();  //virtual destructor 
    virtual const char* what() const throw();  //virtual function
}

Tags: C C++

Posted on Mon, 13 Sep 2021 23:27:45 -0400 by iijb