异常不是错误,异常是程序中可预料到的另一条执行分支,是可预见的。错误是不可预料的。
C++内置了异常处理的语法元素try...catch...,如下:
C++通过throw语句抛出异常信息:
上图中throw 0抛出异常后,程序就立即返回了。return代表正常的返回,throw代表异常的返回值。
C++异常处理分析:
throw抛出的异常必须被catch处理
当前函数能够处理异常,程序继续往下执行
当前函数无法处理异常,则函数停止执行并返回
未被处理的异常则顺着函数调用栈向上传播:
异常的示例程序如下:
1 #include <iostream> 2 3 using namespace std; 4 5 double divide(double a, double b) 6 { 7 const double delta = 0.000000000000001; 8 double ret = 0; 9 10 if( !((-delta < b) && (b < delta)) ) { 11 ret = a / b; 12 } 13 else { 14 throw 0; // 产生除 0 异常 15 } 16 17 return ret; 18 } 19 20 int main() 21 { 22 cout << "main() begin " << endl; 23 24 try 25 { 26 divide(1, 0); 27 } 28 catch(...) 29 { 30 cout << "Divided by zero" << endl; 31 } 32 33 cout << "main() end " << endl; 34 return 0; 35 }
执行结果如下:
26行的异常被28行的catch捕获,处理完这个异常之后,程序继续向下执行,33行成功打印出信息。
更改程序如下:
1 #include <iostream> 2 3 using namespace std; 4 5 double divide(double a, double b) 6 { 7 const double delta = 0.000000000000001; 8 double ret = 0; 9 10 if( !((-delta < b) && (b < delta)) ) { 11 ret = a / b; 12 } 13 else { 14 throw 0; // 产生除 0 异常 15 } 16 17 return ret; 18 } 19 20 int main() 21 { 22 cout << "main() begin " << endl; 23 24 try 25 { 26 int c = divide(1, 0); 27 28 cout << "c = " << c << endl; 29 } 30 catch(...) 31 { 32 cout << "Divided by zero" << endl; 33 } 34 35 cout << "main() end " << endl; 36 return 0; 37 }
执行结果如下:
可以看到第28行的打印没有输出。
如果try中的语句没有发生异常,catch中的语句是不会执行的。
同一个try语句可以跟上多个catch语句:
异常处理的匹配规则:
捕捉异常的示例程序:
1 #include <iostream> 2 3 using namespace std; 4 5 double divide(double a, double b) 6 { 7 const double delta = 0.000000000000001; 8 double ret = 0; 9 10 if( !((-delta < b) && (b < delta)) ) { 11 ret = a / b; 12 } 13 else { 14 throw 0; // 产生除 0 异常 15 } 16 17 return ret; 18 } 19 20 void Demo1() 21 { 22 try 23 { 24 throw 'c'; 25 } 26 catch(int i) 27 { 28 cout << "catch (int i) " << endl; 29 } 30 catch(double d) 31 { 32 cout << "catch(double d)" << endl; 33 } 34 catch(char c) 35 { 36 cout << "catch(char c)" << endl; 37 } 38 } 39 40 int main() 41 { 42 cout << "main() begin " << endl; 43 44 try 45 { 46 int c = divide(1, 0); 47 48 cout << "c = " << c << endl; 49 } 50 catch(...) 51 { 52 cout << "Divided by zero" << endl; 53 } 54 55 Demo1(); 56 57 cout << "main() end " << endl; 58 return 0; 59 }
执行结果如下:
异常捕捉示例程序:
1 #include <iostream> 2 3 using namespace std; 4 5 double divide(double a, double b) 6 { 7 const double delta = 0.000000000000001; 8 double ret = 0; 9 10 if( !((-delta < b) && (b < delta)) ) { 11 ret = a / b; 12 } 13 else { 14 throw 0; // 产生除 0 异常 15 } 16 17 return ret; 18 } 19 20 void Demo1() 21 { 22 try 23 { 24 throw 'c'; 25 } 26 catch(int i) 27 { 28 cout << "catch (int i) " << endl; 29 } 30 catch(double d) 31 { 32 cout << "catch(double d)" << endl; 33 } 34 catch(char c) 35 { 36 cout << "catch(char c)" << endl; 37 } 38 } 39 40 void Demo2() 41 { 42 throw "D.T.Software"; // const char* 43 } 44 45 int main() 46 { 47 cout << "main() begin" << endl; 48 49 try 50 { 51 double c = divide(1, 1); 52 53 cout << "c = " << c << endl; 54 } 55 catch(...) 56 { 57 cout << "Divided by zero..." << endl; 58 } 59 60 Demo1(); 61 62 try 63 { 64 Demo2(); 65 } 66 catch(char* c) 67 { 68 cout << "catch(char* c)" << endl; 69 } 70 catch(const char* cc) 71 { 72 cout << "catch(char* cc)" << endl; 73 } 74 catch(...) 75 { 76 cout << "catch(...)" << endl; 77 } 78 79 cout << "main() end" << endl; 80 81 return 0; 82 }
执行结果如下:
catch捕捉异常时,是类型严格匹配的,不会进行类型转换。字符串是const char*类型。
小结:
C++中直接支持异常处理的概念。
try...catch...是C++中异常处理的专用语句。
try语句处理正常代码逻辑,catch语句处理异常情况。
同一个try语句可以跟上多个catch语句。
异常处理必须严格匹配,不进行任何的类型转换。