exception handling
1. Introduction
Like java, the program often encounters some errors when running. If it is not handled, it is likely to cause the program to crash. The C + + exception handling mechanism allows us to catch and handle these errors
The C + + exception handling mechanism involves three keywords: try, catch and throw.
2. Common runtime errors
Runtime errors refer to errors that occur during the operation of the program, such as divisor 0, memory allocation failure, array out of bounds, file nonexistence, etc. C++ The Exception mechanism is introduced to solve runtime errors.
Case:
#include <iostream> #include <string> using namespace std; int main(){ string str = "http://c.biancheng.net"; char ch1 = str[100]; //The subscript is out of bounds, and ch1 is the garbage value cout<<ch1<<endl; char ch2 = str.at(100); //The subscript is out of bounds and an exception is thrown cout<<ch2<<endl; return 0; }
str[] 😕/ It will not check that the subscript is out of bounds and will not throw an exception, so try will not detect an error even if there is an error
//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.
Try catch exception
#include <iostream> #include <exception> using namespace std; int main(int argc, char const *argv[]) { string str = "http://c.biancheng.net"; try { char ch1 = str[100];//Because [] will not check for subscript out of bounds and will not throw exceptions, try cannot detect errors even if there are 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. cout << ch1 << endl; } catch (exception e) { cout << "[1]out of bound!" << endl; } try { char ch2 = str.at(100);//It is recommended to use at, which will check that the subscript is out of bounds cout << ch2 << endl; } catch (exception &e) { //The exception class is located in the < exception > header file cout << "[2]out of bound!" << endl; } system("pause"); return 0; }
3. throw an exception
Throw can throw an exception. Custom exception
#include <iostream> #include <string> #include <exception> using namespace std; void func() { throw "Unknown Exception"; //Throw exception cout << "[1]This statement will not be executed." << endl; } int main() { try { func(); cout << "[2]This statement will not be executed." << endl; } catch (const char *&e) { cout << e << endl; } system("pause"); return 0; }
4.catch exception type
Since an exception is a piece of data, it should have a data type. C++ It is specified that the exception type can be basic types such as int, char, float and bool, or Pointer Aggregate types such as, array, string, structure, class, etc. Exceptions thrown by the C + + language itself and functions in the standard library are exceptions of the exception class or its subclasses. That is, when an exception is thrown, an object of the exception class or its subclass will be created.
We can regard catch as a function with no return value. When an exception occurs, catch will be called and receive arguments (exception data).
In general, catch has a process of "matching arguments with formal parameters at run time" compared with real function calls.
————————It is basically consistent with java. Note that in the eyes of C + +, dividing by 0 is unacceptable and should not be treated as an exception.
#include <iostream> #include <string> using namespace std; class Base { }; class Derived : public Base { }; int main() { try { throw Derived(); //Throwing your own exception type is actually creating an anonymous object of Derived type cout << "This statement will not be executed." << endl; } catch (int) { cout << "Exception type: int" << endl; } catch (char *) { cout << "Exception type: cahr *" << endl; } catch (Base) { //Successful matching (upward transformation) cout << "Exception type: Base" << endl; } catch (Derived) { cout << "Exception type: Derived" << endl; } system("pause"); return 0; }
5.catch type conversion during matching
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.
Case:
#include <iostream> using namespace std; int main() { int nums[] = {1, 2, 3}; try { throw nums; cout << "This statement will not be executed." << endl; } catch (const int *) { cout << "Exception type: const int *" << endl; } system("pause"); return 0; }
Exception type: const int *
Please press any key to continue
5.throw exception specification
Throw keyword can be used not only in the function body to throw an exception, but also between the function header and the function body to indicate the type of exception that the current function can throw. This is called exception specification.
double func (char param) throw (int);
This statement declares a function named func, its return value type is double, has a char type parameter, and can only throw int type exceptions. If other types of exceptions are thrown, try cannot catch them and can only terminate the program.
If the function throws multiple types of exceptions, it can be separated by commas:
double func (char param) throw (int, char, exception);
If the function does not throw any exceptions, nothing is written in ():
double func (char param) throw ();
In this way, func() function cannot throw any type of exception. Even if it is thrown, try cannot detect it.
1. Exception specification in virtual function
C + + stipulates that the exception specification of derived class virtual functions must be as strict as or more strict than that of base class virtual functions. Only in this way can we ensure that the exception specification of the base class member function is not violated when the derived class virtual function is called through the base class pointer (or reference). Take the following example:
class Base{ public: virtual int fun1(int) throw(); virtual int fun2(int) throw(int); virtual string fun3() throw(int, string); }; class Derived:public Base{ public: int fun1(int) throw(int); //wrong! Exception specification is not as strict as throw() int fun2(int) throw(int); //yes! Have the same exception specification string fun3() throw(string); //yes! Exception specification is stricter than throw(int,string) }
2) Exception specification and function definition and function declaration
C + + stipulates that the exception specification must be specified in the function declaration and function definition at the same time, and must be strictly consistent, not more strict or more relaxed.
Simply put: consistent with the statement.
//wrong! There is an exception specification in the definition, not in the declaration void func1(); void func1() throw(int) { } //wrong! The exception specification in the definition and declaration is inconsistent void func2() throw(int); void func2() throw(int, bool) { } //yes! The exception specifications in the definition and declaration are strictly consistent void func3() throw(float, char*); void func3() throw(float, char*) { }
Note: discard the exception specification and do not use it again
The original intention of exception specification is good. It hopes to let programmers know what type of exception the function will throw immediately after seeing the definition or declaration of the function, so that programmers can use try catch to catch it. If there is no exception specification, programmers must read the function source code to know what exceptions the function will throw.
But sometimes it's not easy. For example, func_ The outer() function may not throw an exception, but it calls another function func_inner(), this function may throw an exception. For another example, the function you write calls the old library function and will not throw an exception at this time, but this function throws an exception after the library is updated. In short, the original intention of exception specification is a little difficult to implement, so the consensus is that it is best not to use exception specification.
Exception specification is a new function of C++98, but later C++11 has abandoned it and is no longer recommended.
6.exception class
C + + exception base class. C++ Exceptions thrown by the language itself or the standard library are subclasses of exception, which is called standard exception (S) tandard Exception).
class exception { public: exception() _GLIBCXX_USE_NOEXCEPT { } Constructor virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;//virtual destructor virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT; //virtual function };
std::exception this exception is the parent of all standard C + + exceptions.
std::bad_alloc this exception can be thrown through new.
std::bad_cast this exception can be passed through dynamic_cast throw.
std::bad_exception this is useful when dealing with unexpected exceptions in C + + programs.
std::bad_typeid this exception can be thrown through typeid.
std::logic_error is an exception that can theoretically be detected by reading the code.
std::domain_error this exception is thrown when an invalid mathematical field is used.
std::invalid_argument this exception is thrown when an invalid parameter is used.
std::length_error this exception will be thrown when too long std::string is created.
std::out_of_range this exception can be thrown through methods, such as std::vector and STD:: BitSet < >:: operator .
std::runtime_error is an exception that cannot theoretically be detected by reading code.
std::overflow_error this exception is thrown when a math overflow occurs.
std::range_error this exception is thrown when trying to store a value that is out of range.
std::underflow_error this exception is thrown when a mathematical underflow occurs.
7. Generic capture
void function(){ try { /* your code */ }catch(...) { /* handler */ } }
8. Custom exception type
#include <iostream> using namespace std; class MyException : public exception { public: MyException(); MyException(string emsg); ~MyException(){}; virtual const char *what() const throw(); protected: string emsg; }; MyException::MyException() : exception() { } MyException::MyException(string emsg) { this->emsg = emsg; } const char *MyException::what() const throw() { return this->emsg.c_str(); } void test() { MyException my("data error"); throw my; cout << "Will not execute" << endl; } int main(int argc, char const *argv[]) { try { test(); } catch (const MyException &e) { cout << e.what() << endl; } system("pause"); return 0; }
data error
Please press any key to continue
9. Summary
Catch: you can directly catch the types to be thrown, including possible conversion types. Compared with java, java needs to wrap exception, and c + + doesn't
exception: unlike java, most of its types do not print by themselves, but need to be customized. In java, there are various systems to help us define exceptions.
argv[])
{
try
{
test();
}
catch (const MyException &e)
{
cout << e.what() << endl;
}
system("pause");
return 0;
}
data error Please press any key to continue. . . ### 9. Summary ​ catch: You can directly capture the types to be thrown, including possible conversion types, compared to java More direct, java Need package exception,c++unwanted ​ exception: differ java,Most of its types will not print by themselves, but need to be customized, java In, there are various systems to help us define exceptions.