C ++ exception handling (try catch throw) completely Raiders

 

The program runs often met with some exceptions, such as:

  • Do division when the divisor is 0;
  • Enter a negative number when the user enters the age;
  • When a new operator dynamically allocated space, leading to not allocate enough space;
  • When accessing array elements, subscript out of range; when you open the file read, file does not exist.


These anomalies, if not identified and treated, it may lead to a crash.

The so-called "treatment", may be give an error message, and then let the program along a path not wrong to continue; it may have to end the program, but do some necessary work before the end, as the data in memory will write files, close open files, free up memory dynamically allocated and so on.

An abnormal situation may not be appropriate treatment immediately, because the exception occurred during the execution of a function, in some cases determined by the caller of the function of how to deal with more appropriate. In particular, such as library functions available to programmers call for completion function independent of the specific application of common functions, during execution rush to deal with exceptions, may not meet the needs of the calling program.

In addition, the anomalous dispersion in the entire processing is not conducive to maintenance of the code, in particular, for the same abnormalities that occur in different places, have to write the same handling code is an unnecessary duplication and redundancy. If we can make an exception occurs in a variety of programs are executed in the same place, this place can focus on the abnormality, the program will be easier to write and maintain.

For these reasons, C ++  introduced exception handling mechanism. The basic idea is: you can not add an exception processing function A discovery in the implementation process, but simply "throw an exception" to the caller A is assumed to be a function of B.

Throwing an exception handling without adding the suspension immediately causes the function A, in this case, B may select the capture function A thrown exception processing, can also choose to ignore. If ignored, this exception will be thrown to the caller B, and so on.

If the layers are not a function of the processing exception, the exception thrown will eventually be the outermost main function. main function should handle the exception. If the main function does not handle the exception, then the program will be suspended immediately abnormally.

The basic syntax of C ++ exception handling

By C ++ throw statement and try ... catch statement to achieve for exception handling. The syntax throw statement is as follows:

throw expression;

The statement throws an exception. Exception is an expression of the type which may be a base type value, may be based.

try ... catch statement syntax is as follows:

try {
    statement group
}
the catch (Exception Type) {
    exception handling code
}
...
the catch (Exception Type) {
    exception handling code
}

catch can have a plurality of, but at least one.

You may wish to try and subsequent {}content referred to "try blocks", the catch and thereafter {}the content is referred to as "catch block."

try ... catch statement execution process is:

  • The try block statements, if the process of implementation is not an exception is thrown, then the implementation of the latter on the implementation last catch block behind the statement, all statements in the catch block will not be executed;
  • If the process executed in the try block throws an exception, then immediately jump to the first "Exception Types" and catch block matches the type of exception thrown exception is thrown after the execution (the exception is referred to as a catch block of the "Capture "), after their execution jumps back to the last catch block continues.


For example, the following program:

  1. #include <iostream>
  2. using namespace std;
  3. int main ()
  4. {
  5. double m ,n;
  6. cin >> m >> n;
  7. try {
  8. cout << "before dividing." << endl;
  9. if( n == 0)
  10. the throw - 1 ; // throws an exception of type int
  11. else
  12. cout << m / n << endl;
  13. cout << "after dividing." << endl;
  14. }
  15. catch(double d) {
  16. cout << "catch(double) " << d << endl;
  17. }
  18. catch(int e) {
  19. cout << "catch(int) " << e << endl;
  20. }
  21. cout << "finished" << endl;
  22. return 0;
  23. }

Run results of the program are as follows:
. 9 6↙
. Before dividing Is
for 1.5
. After dividing Is
Finished

explained when n is not 0, try not throw an exception block. Therefore, the normal procedure in the try block after the implementation, across all catch block to continue, a catch block is not executed.

Result of the program may run as follows:
. 9 0↙
. Before dividing Is
the catch \ (int) -1
Finished

when n is 0, try block throws an exception integer. After an exception is thrown, try to immediately stop the execution block. The exception is captured Integer first matching catch block type, i.e. into the catch(int e)block execution, the catch block after the implementation of the program and ending the execution until the end of normal.

If an exception is not caught catch block, e.g., to catch(int e), to catch(char e), when the input of n is 0, no exception is thrown integer capture the catch block, the exception will not be processed, then the program will be suspended immediately, try ... catch behind the content will not be executed.

Able to capture any exceptions catch statement

If you want to throw no matter what type of anomaly can capture, catch block can be written as follows:

catch(...) {
    ...
}

Such blocks can catch any exception capture has not been captured. For example, the following program:

  1. #include <iostream>
  2. using namespace std;
  3. int main ()
  4. {
  5. double m, n;
  6. cin >> m >> n;
  7. try {
  8. cout << "before dividing." << endl;
  9. if (n == 0)
  10. the throw - 1 ; // throws an exception integer
  11. else if (m == 0)
  12. the throw - 1.0 ; // throw double abnormalities
  13. else
  14. cout << m / n << endl;
  15. cout << "after dividing." << endl;
  16. }
  17. catch (double d) {
  18. cout << "catch (double)" << d << endl;
  19. }
  20. catch (...) {
  21. cout << "catch (...)" << endl;
  22. }
  23. cout << "finished" << endl;
  24. return 0;
  25. }

Run results of the program are as follows:
. 9 0↙
. Before dividing Is
the catch (...)
Finished

when n is 0, integer thrown exception is catchy(...)captured.

Result of the program may run as follows:
0 6↙
. Before dividing Is
the catch (double) -1
Finished

when m is 0, a double throw type of exception. Although catch (double)and catch(...)can match the exception, but catch(double)is the first to match the catch block, so it will be executed, but does not execute catch(...)the block.

Because catch(...)can match any type of exception, the catch block behind it really is not effective, so do not write it in front of the other catch block.

The exception is thrown again

If a function is thrown during the execution of the exception is captured and processed within the catch block function, then the exception is not thrown to the calling function (also referred to as "upper layer function"); if exception is not handled in this function, then it will be thrown on the function layer. For example, the following program:

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class CException
  5. {
  6. public:
  7. string msg;
  8. CException(string s) : msg(s) {}
  9. };
  10. double Devide(double x, double y)
  11. {
  12. if (y == 0)
  13. throw CException("devided by zero");
  14. cout << "in Devide" << endl;
  15. return x / y;
  16. }
  17. int CountTax(int salary)
  18. {
  19. try {
  20. if (salary < 0)
  21. throw - 1;
  22. cout << "counting tax" << endl;
  23. }
  24. catch (int) {
  25. cout << "salary < 0" << endl;
  26. }
  27. cout << "tax counted" << endl;
  28. return salary * 0.15;
  29. }
  30. int main ()
  31. {
  32. double f = 1.2;
  33. try {
  34. CountTax(-1);
  35. f = Devide(3, 0);
  36. cout << "end of try block" << endl;
  37. }
  38. catch (CException e) {
  39. cout << e.msg << endl;
  40. }
  41. cout << "f = " << f << endl;
  42. cout << "finished" << endl;
  43. return 0;
  44. }

The output program is as follows:
the salary <0
Tax counted
devided by ZERO
F = 1.2
Finished

CountTa function after an exception is thrown handle, this exception will not continue to be thrown to the caller, i.e. the main function. Thus the main function in the try block, the statement after the normal execution can CountTax, i.e. executes f = Devide(3, 0);.

Line 35, Devide not function throws an exception handling, the exception will be thrown to the caller Devide function, that is the main function. After this exception is thrown, the function ends immediately devide, line 14 will not be executed, the function does not return a value, which can not be seen from the values of the modified row 35 of f.

Devide function thrown exception is caught in the main function of the type of the matching catch block. E target line 38 is initialized with a copy constructor.

If an exception is an object of a derived class, the type of exception that the catch block of the base class, then it is possible to match the two because a derived object is a base class object.

Although the function parameter tells the caller can pass or return values by reference to the occurrence of an exception, but this way, then each function call must determine whether there has been an exception, this is too much trouble when the function is invoked multiple. With the exception handling mechanism can be multiple function calls are written in a try block, any one call occurs exceptions are matching catch block catches and processed, it is not required after each invocation determine whether an abnormality has occurred .

Sometimes, although an exception was processed in a function, but still want to be able to inform the caller to let the caller know there had been an exception, allowing for further processing. Thrown meet this need in the catch block. E.g:

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. int CountTax(int salary)
  5. {
  6. try {
  7. if( salary < 0 )
  8. throw string("zero salary");
  9. cout << "counting tax" << endl;
  10. }
  11. catch (string s ) {
  12. cout << "CountTax error : " << s << endl;
  13. the throw ; // continue to throw an exception caught
  14. }
  15. cout << "tax counted" << endl;
  16. return salary * 0.15;
  17. }
  18. int main ()
  19. {
  20. double f = 1.2;
  21. try {
  22. CountTax(-1);
  23. cout << "end of try block" << endl;
  24. }
  25. catch(string s) {
  26. cout << s << endl;
  27. }
  28. cout << "finished" << endl;
  29. return 0;
  30. }

The output of the program are as follows:
CountTax error: the salary ZERO
ZERO the salary
Finished

line 14 throw;does not indicate what kind of exception is thrown, the throw is thus caught exception catch block, i.e. string ( "zero salary"). This exception will be caught in the catch block main function.

Abnormal function declaration list

In order to enhance the readability and maintainability of the program, the programmer when using a function able to see what this function may throw an exception, C ++ allows function declaration and definition, plus it can throw abnormal list of specific wording as follows:

void func() throw (int, double, A, B, C);

or

void func() throw (int, double, A, B, C){...}

The above wording may indicate throw int func-type, double-type and A, B, C are three types of anomalies. Abnormal declaration list can be written in the function declaration, can also be written when the function is defined. If the two are written, the two should be the same.

If an exception written declaration list follows:

void func() throw ();

Then the func function does not throw any exceptions.

If a function does not explain what type of exception can be thrown, you can throw any type of exception.

If an exception is thrown its function declaration not in the list of exceptions, does not raise an error at compile time, but at run time, Dev C compiler out of the program will go wrong ++; compile it with Visual Studio 2010 program is not wrong, abnormal can not afford to declare a list of practical effect.

C ++ standard exception classes

C ++ standard library class represents some exceptions, these classes are derived from the class of exception. Several commonly used exception classes as shown in FIG.


Figure 1: commonly used exception classes


bad_typeid, bad_cast, bad_alloc, ios_base :: failure, out_of_range are derived class exception class. C ++ program when confronted with certain exceptions, even if the program did not write a throw statement, will automatically target the abnormal class thrown. These anomalies are also called class member function what returns a string description of exception. Using these exception classes need to include the header file stdexcept.

The following were introduced more than a few exception classes. Output This section of the program in order to prevail in Visual Studio 2010, Dev C ++ compiler program output is different.

1) bad_typeid

When using typeid operator, if it is an operand polymorphic class pointer , and this pointer is NULL, this exception will be thrown.

2) bad_cast

Dynamic_cast carried out with polymorphic base class object (or reference) to cast from a derived class reference, if the conversion is unsafe, this exception will be thrown. Program example below:

  1. #include <iostream>
  2. #include <stdexcept>
  3. using namespace std;
  4. class Base
  5. {
  6. virtual void func() {}
  7. };
  8. class Derived : public Base
  9. {
  10. public:
  11. void Print() {}
  12. };
  13. void PrintObj(Base & b)
  14. {
  15. try {
  16. Derived & rd = dynamic_cast <Derived &>(b);
  17. // If this conversion safety, throws an exception bad_cast
  18. rd.Print();
  19. }
  20. catch (bad_cast & e) {
  21. cerr << e.what() << endl;
  22. }
  23. }
  24. int main ()
  25. {
  26. Base b;
  27. PrintObj(b);
  28. return 0;
  29. }

The output procedure is as follows:
Bad dynamic_cast!

In PrintObj function, whether referenced by dynamic_cast b is a Derived object is detected, and if so, call its Print member function; if not, it throws an exception, does not call Derived :: Print.

3) bad_alloc

When dynamic memory allocation with the new operator, if there is not enough memory, this exception is thrown. Program example below:

  1. #include <iostream>
  2. #include <stdexcept>
  3. using namespace std;
  4. int main ()
  5. {
  6. try {
  7. char * the p- = new new char [ 0x7fffffff ]; // Could not allocate so much space, it will throw an exception
  8. }
  9. catch (bad_alloc & e) {
  10. cerr << e.what() << endl;
  11. }
  12. return 0;
  13. }

The output program is as follows:
Bad Allocation
ios_base :: failure

in the default state, the input and output stream object is not thrown. If you set some flags member function with exceptions stream object, in the event will be thrown open file error, read the case file the end of the input stream and so on. Not repeat them here.

4) out_of_range

With a vector or at a member function string according to the index when accessing elements, if the index is out of range, it will Thrown. E.g:

  1. #include <iostream>
  2. #include <stdexcept>
  3. #include <vector>
  4. #include <string>
  5. using namespace std;
  6. int main ()
  7. {
  8. vector<int> v(10);
  9. try {
  10. v . AT ( 100 ) = 100 ; // throws an exception out_of_range
  11. }
  12. catch (out_of_range & e) {
  13. cerr << e.what() << endl;
  14. }
  15. string s = "hello";
  16. try {
  17. C char = S . AT ( 100 ); // throws an exception out_of_range
  18. }
  19. catch (out_of_range & e) {
  20. cerr << e.what() << endl;
  21. }
  22. return 0;
  23. }

The output of the program are as follows:
invalid Vector <T> subscript
invalid String position

if v.at(100)changed v[100], will be s.at(100)changed s[100], the program will not throw an exception (but may cause the program to crash). Because at member function detects subscript out of bounds and throws an exception, and operator [] does not. operator [] is compared to the benefits at no judge whether the subscript is out of range, speed of execution and therefore faster.

Guess you like

Origin www.cnblogs.com/lx17746071609/p/11589246.html