An introduction exception that allows a function to throw an exception when it finds an error that it cannot handle, hoping that its callers can handle the problem directly or indirectly. While the traditional error processing technology, check to a local can not handle the problem: 1. Terminate the program (for example, Atol,atoi, enter NULL, will produce a segment error, causing the program to exit unexpectedly, if there is no core file, the person who is looking for the problem will be crazy) 2. Returns a value that represents the error ( Many system functions, such as malloc, insufficient memory, allocation failure, return a null pointer, 3. Returns a legal value that allows the program to be in some sort of illegal state (something that some third-party libraries really do) 4. Invokes a function that is prepared in the event of an "error". The first case is not allowed, the unconditional termination of the application of the library can not be used in the machine can not be in the program. The second case, more commonly used, but sometimes inappropriate, such as the return error code is int, each call to check the error value, very inconvenient, but also easy to double the program size (but to precisely control the logic, I think this is a good way). In the third case, it is easy to mislead the caller, in case the caller does not check the global variable errno or otherwise checks the error, it is a disaster, and this method does not work well in concurrent situations. As for the fourth situation, I feel less use, and the callback code should not appear more. Using exceptions, the error and processing are separated, the library function throws an exception, the caller catches the exception, the caller can know that the Program function library call error, and to deal with, and whether to terminate the program is in the caller's hand. However, error handling is still a difficult task, and C + + 's exception mechanism provides programmers with a way to handle errors, allowing programmers to handle errors in a more natural way. Introduction to exception actual combat suppose we write a program that converts two strings entered by the user to integers, add output, and generally we write char *str1 = "1", *str2 = "2", int num1 = Atoi (str1), int num2 = atoi (str2);p R INTF ("Sum is%d\n", NUM1 + num2); Assuming that the user entered Str1,str2, if both str1 and str2 are integer-type strings, this code works correctly, but the user's input is likely to be mistakenly manipulated, with illegal characters entered, such as char *str1 = "1", *str2 = "a"; int num1 = Atoi (str1); int num2 = Atoi (str2);p rintf ("Sum is%d\n", NUM1 + num2); this time the result is 1, because atoi (STR2) returns 0. If user input is this: Char *str1 = "1", *str2 = null;int num1 = atoi (str1), int num2 = atoi (str2);p rintf ("Sum is%d\n", NUM1 + num2); then this piece of code will have an error Error, the program exits unexpectedly. Atoi I think is a more dangerous function, if in an important system, the caller does not know, passed in a null character, the program is abnormally exited, resulting in service interruption, or the passing of illegal characters, the result returns 0, the code continues to go on, in the complex system to locate the problem is really not easy. So the more appropriate way, we use abnormal treatment to transform a safe Atoi method, called Parsenumber. Class Numberparseexception {};bool isnumber (char * str) {using namespace std; if (str = = NULL) return false; int len = St Rlen (str); if (len = = 0) return false; BOOL Isanumber = false; Char ch; for (int i = 0; i < len; i++) {if (i = = 0 && (str[i] = = '-' | | str[i] = = ' + ')) continue; if (IsDigit (str[i))) {Isanumber = true;} else {isanumber = false; break;}} return isanumber;} int Parsenumber (char * str) throw (numberparseexception) {if (!isnumber (str)) throw numberparseexception (); return Atoi (s TR);} In the code above, Numberparseexception is a custom exception class, when we detect when the incoming STR is not a number, throw a number conversion exception, let the caller handle the error, which is more than passing in a null string, resulting in the end of the paragraph error program is much better, The caller can catch this exception, decide whether to end the program, or pass in a non-integer string, return 0 is better, the program error, but continue to silently execute. So the code we wrote earlier could be modified as follows: char *str1 = "1", *str2 = NULL; try {int num1 = Parsenumber (str1); int num2 = Parsenumber (str2); printf ("Sum is%d\n", NUM1 + num2);} catch (Numberparse Exception) {printf ("Input is not an integer \ n");} The result of this code is to print out "input is not an integer". Assuming this code is running in a game statistics system, the system needs to regularly from a large number of files to count the number of users into the game Channel 1 and Game Channel 2 times, STR1 represents into the game Channel 1 times, STR2 represents the number of channels to enter 2, If an exception is not used, when the input is NULL the program causes the entire system to be down, and when the input is an illegal integer, the results are all wrong, and the program still silently "executes correctly". The input is illegal, throwing numberparseexception, even if the caller does not consider the input to be illegal, for example: char *str1 = "1", *str2 = "12,"; int num1 = Parsenumber (STR1); int num2 = Parsenumber (STR2); printf ("Sum is%d\n", NUM1 + num2), even if the caller is careless, there is no catch exception, the program will throw the Numberparseexception, the program goes down, will leave the Coredump file, the caller through the "GDB program name Coredump file ", see the program down the stack, know that the program is running, there is an illegal integer character, then he quickly know the problem, will learn, the above code to char *str1 =" 1 ", *str2 = NULL; try {int num1 = Parsenumber (str1); int num2 = Parsenumber (str2); printf ("Sum is%d\n", NUM1 + num2);} catch (Numberparse Exception) {printf ("Input is not an integer \ n"), the path of the print file, the line number, the STR1,STR2, and so on are enough to locate the problem by themselves} So, the next time the program has a problem, the caller can locate the problem, which is the exception of the error handling method, Separate the wrong Discovery (Parsenumber) from the wrong handling (game stats code). This article introduces exception throws and captures, as well as unusual usage scenarios, and then begins aStep-by-step explanation of C + + exceptions. Exceptions that describe functions and functions that might throw an exception set are valuable as part of a function declaration, such as void f (int a) throw (x2,x3), which means that f () can only throw two exception x2,x3, and exceptions that derive from those types, but do not throw other exceptions. If the F function violates this rule and throws an exception other than x2,x3, such as X4, then when the function f throws a X4 exception, it is converted to a std::unexpected () call, which is called std::terminate () by default, usually called Abort (). If the function is not described with an exception, it is assumed that he may throw any exception. For example: int f (); A function that throws any exception without any exceptions can be represented by a null table: int g () throw (); The code that does not throw any exceptions to catch exception catches is generally as follows: try {throw E ();} catch (H h) {//When can we get here}1. If H and e are the same type 2. If h is the base class of E 3. If H and e are both pointer types, and 1 or 2 are set to 4 for the type they reference. If both H and e are reference types, and the type referenced by 1 or 2 to H is in principle, the exception is copied at the time of the throw, and the last exception we catch is just a copy of the As we should not throw an exception that is not allowed to throw a copy that is not allowed. In addition, we can add a const to the type used to catch the exception, just as we can add a const to the function, restricting us from modifying the caught exception. Also, if the exception is caught when H and e are not reference types or pointer types, and H is the base class of E, then the H object is actually h H = e (), and the last caught exception object H loses the additional carrying information of E. The order of exception handling we previously wrote the Parsenumber function will throw numberparseexception, this function just to determine whether the number is thrown exception, but not considered, but this string represents the integer is too large, overflow, throws an exception overflow. Class Numberparseexception {};class overflow:public numberparseexception {}; Assuming that our parsenumber function has been detected as an integer overflow of strings, in this case , the overflow exception is thrown, so the exception capture code is as follows: char *str1 = "1", *str2 = NULL; try {int num1 = Parsenumber (str1); int num2 = PArsenumber (STR2); printf ("Sum is%d\n", NUM1 + num2); } catch (Overflow) {//handle Overflow or any exception derived by Overflow} catch (numberparseexception) {// Handling numberparseexception exceptions that are not overflow} exception organization This hierarchy is important for the robustness of code, because after a library function is published, it is not possible to not add new exceptions, like our Parsenumber, The first time you publish just consider whether the input is an integer error, the second time when the issue is considered to determine whether the input string as an integer is too large overflow, for a function after the publication no longer add new exceptions, almost all library functions are unacceptable. If there is no exception hierarchy, when the function is added to the new exception description, we may have to modify the code, for each call to the function of the place to add the corresponding catch new exception statement, which makes you bored, it is easy for programmers to forget to add an exception to the list, resulting in the exception is not caught, abnormal exit. With the exception of the hierarchy, after the function upgrade, for example, our Parsenumber added the Overflow exception description, the function caller only need to add catch (Overflow) in the calling scene of their own interest, and do the processing on the line, If you don't care about overflow errors, you don't even have to modify the code. Uncaught exception if the thrown exception is not captured, then the function std::terminate () is called, and by default it is called Abort, which is the correct choice for most users, especially in the phase of the error of the wrong program (calling abort produces the Coredump file, The use of the Coredump file can refer to the blog "Learn to use Core Dump Debug program error"). If we want to ensure cleanup when an uncaught exception occurs, you can add a catch exception handler in main outside of all the exceptions that really need attention, for example: int main () {try {//...} catch (Std::range_error) { Cerr << "Range error\n"; } catch (Std::bad_alloc) {cerr << "new run out of memory\n";} catch (...) { //.. }} This allows you to catch all exceptions except those that are constructed and refactored in global variables (if you want to get control, the only way is SET_UNEXPECTED). where catch (...) means catching all exceptions, and usually doing some cleanup work in the process code. Re-throw when we catch an exception and find that we can't handle it, in which case we'll do something we can do locally, then throw the exception again, and let the exception be handled in the most appropriate place. For example: void Downloadfilefromserver () {try {connect_to_server ();//...} catch (Networkexception) {if (Can_handle_it_complet Ely) {//handle network exception, such as re-connect} else {throw;}} This function is to download the file from the remote server, internal calls to connect to the remote server function, but there may be a network exception, if multiple reconnection cannot succeed, throw this network exception, let the upper processing. The re-throw is represented by a throw without an operand, but if it is re-thrown and no exception can be re-thrown, terminate () is called; Suppose Networkexception has two derived exceptions called Ftpconnectexception and Httpconnectexception, which is thrown when Connect_to_server is called Httpconnectexception , the call Downloadfilefromserver can still catch the exception httpconnectexception. Standard exception here, you have basically used the exception, but if you are a function developer, and need to use the function to others, when using exceptions, will involve the custom exception class, but the C + + standard has defined a part of the standard exception, please reuse these exceptions as possible, the standard exception reference HTTP/ www.cplusplus.com/reference/std/stdexcept/Although the C + + standard exception is relatively small, but as a function developer, as much as possible to reuse the C + + standard exception, as a function caller can spend less time to understand your custom exception class, Better to call the functions you have developed. Summary This article is simply from the exception of the use of the scenario, and then introduce the basic use of the exception, some advanced exception usage is not listed, detailed information can refer to C + + 's parent C + + programming language exception handling.
C + + Exception learning