嵌入式学习-C嘎嘎-Day06
[1. 什么是异常?](#1. 什么是异常?)
[2. 抛出异常](#2. 抛出异常)
[3. 捕获异常](#3. 捕获异常)
[4. 标准异常族](#4. 标准异常族)
[5. 异常捕获技巧](#5. 异常捕获技巧)
[5.1 捕获基类异常](#5.1 捕获基类异常)
[5.2 多重捕获](#5.2 多重捕获)
1. 什么是异常?
异常是程序在运行期间产生的问题,即没有语法错误,出现的是逻辑错误,C++提供了一种转移程序控制权的方式:
- 异常经过程序员正确处理,继续运行;
- 异常没有经过程序员正确处理,运行终止。
例如之前使用string的at函数,范围越界的问题等。
处理异常的方式有两种:
- 抛出异常 throw
- 捕获异常 try-catch
2. 抛出异常
使用throw关键字可以抛出一个异常对象,throw可以抛出任何类型的异常对象,抛出到当前代码调用的上一级。
#include <iostream>`
`using` `namespace std;`
`double` `divide(double a,double b)`
`{`
`if(b ==` `0)`
`throw` `"除数不能为0!!!";`
`return a/b;`
`}`
`int` `main()`
`{`
` cout <<` `divide(3,2)` `<< endl;` `// 1.5`
` cout <<` `divide(2,0)` `<< endl;` `// 终止运行`
` cout <<` `"程序运行结束"` `<< endl;`
`return` `0;`
`}`
`
3. 捕获异常
捕获异常分为try代码块和catch代码块,try块中放置可能抛出异常的代码,catch块放置异常类型匹配的代码,处理逻辑如下:
情况1:抛出异常并捕获成功
#include <iostream>`
`using namespace std;`
`double divide(double a,double b)`
`{`
` if(b == 0)`
` throw "除数不能为0!!!";`
` return a/b;`
`}`
`int main()`
`{`
` try`
` {`
` cout << divide(2,0) << endl;`
` cout << "A" << endl;`
` }catch(const char* e)`
` {`
` cout << e << endl;`
` // 正常开发下,需要修复逻辑错误`
` }`
` cout << "程序运行结束" << endl;`
` return 0;`
`}
情况2:抛出异常,捕获失败
#include <iostream>`
`using namespace std;`
`double divide(double a,double b)`
`{`
` if(b == 0)`
` throw "除数不能为0!!!";`
` return a/b;`
`}`
`int main()`
`{`
` try`
` {`
` cout << divide(2,0) << endl;`
` cout << "A" << endl;`
` }catch(int e)`
` {`
` cout << e << endl;`
` // 正常开发下,需要修复逻辑错误`
` }`
` cout << "程序运行结束" << endl;`
` return 0;`
`}
情况3:没有抛出异常,正常直接try块结束。
#include <iostream>`
`using namespace std;`
`double divide(double a,double b)`
`{`
` if(b == 0)`
` throw "除数不能为0!!!";`
` return a/b;`
`}`
`int main()`
`{`
` try`
` {`
` cout << divide(2,1) << endl;`
` cout << "A" << endl;`
` }catch(int e)`
` {`
` cout << e << endl;`
` // 正常开发下,需要修复逻辑错误`
` }`
` cout << "程序运行结束" << endl;`
` return 0;`
`}
异常如果不在当前层次进行处理,也可以交给上一级进行处理,但是如果主函数中还没有正确处理,则程序终止。
#include <iostream>`
`using namespace std;`
`double divide(double a,double b)`
`{`
` if(b == 0)`
` throw "除数不能为0!!!";`
` return a/b;`
`}`
`void test()`
`{`
` try`
` {`
` cout << divide(2,0) << endl;`
` cout << "A" << endl;`
` }catch(int e)`
` {`
` cout << "B" << endl;`
` cout << e << endl;`
` // 正常开发下,需要修复逻辑错误`
` }`
`}`
`int main()`
`{`
` try`
` {`
` test();`
` }catch(const char* e)`
` {`
` cout << "C" << endl;`
` cout << e << endl;`
` // 正常开发下,需要修复逻辑错误`
` }`
` cout << "程序运行结束" << endl;`
` return 0;`
`}
4. 标准异常族
C++为常见的异常类型进行层次划分,通过继承实现。
使用标准异常族需要引入头文件 #include <stdexcept>
自定义异常类型应该通过继承加入上面的结构。
#include <iostream>`
`#include <stdexcept> // 头文件`
`using namespace std;`
`class ZeroException:public exception`
`{`
`public:`
` // throw() 是异常规格说明,表示what函数不会抛出任何异常`
` const char* what() const throw()`
` {`
` return "除数不能为0!!!";`
` }`
`};`
`double divide(double a,double b)`
`{`
` if(b == 0)`
` throw ZeroException();`
` return a/b;`
`}`
`int main()`
`{`
` try`
` {`
` cout << divide(2,0) << endl;`
` cout << "A" << endl;`
` }catch(const ZeroException& e)`
` {`
` cout << e.what() << endl;`
` // 正常开发下,需要修复逻辑错误`
` }`
` cout << "程序运行结束" << endl;`
` return 0;`
`}
5. 异常捕获技巧
5.1 捕获基类异常
所有抛出的派生类异常对象都可以被其基类异常类型捕获。
#include <iostream>`
`#include <stdexcept> // 头文件`
`using namespace std;`
`void poly_except()`
`{`
` int a = 1;`
` if(a == 1)`
` {`
` throw out_of_range("hah");`
` }else {`
` throw domain_error("随便");`
` }`
`}`
`int main()`
`{`
` try`
` {`
` poly_except();`
` }catch(const logic_error& e)`
` {`
` cout << e.what() << endl;`
` // TODO 修复逻辑代码`
` }`
` cout << "程序运行结束" << endl;`
` return 0;`
`}
5.2 多重捕获
可以使用多个catch块配合try块进行异常捕获,catch的顺序要求派生类异常先捕获,基类异常后捕获。
#include <iostream>`
`#include <stdexcept> // 头文件`
`using namespace std;`
`void poly_except()`
`{`
` int a = 2;`
` if(a == 1)`
` {`
` string s;`
` s.at(-1);`
` }else {`
` throw underflow_error("f");`
` }`
`}`
`int main()`
`{`
` try`
` {`
` poly_except();`
` }catch(const out_of_range& e)`
` {`
` cout << "A" << endl;`
` }catch(const domain_error& e)`
` {`
` cout << "B" << endl;`
` }catch(const logic_error& e)`
` {`
` cout << "C" << endl;`
` }catch(const exception& e)`
` {`
` cout << "D" << endl;`
` }`
` cout << "程序运行结束" << endl;`
` return 0;`
`}
还可以单独使用一个...捕获所有异常,但是不推荐。
#include <iostream>`
`#include <stdexcept> // 头文件`
`using namespace std;`
`void poly_except()`
`{`
` int a = 2;`
` if(a == 1)`
` {`
` string s;`
` s.at(-1);`
` }else {`
` throw "fdfdfd";`
` }`
`}`
`int main()`
`{`
` try`
` {`
` poly_except();`
` }catch(...)`
` {`
` cout << "A" << endl;`
` }`
` cout << "程序运行结束" << endl;`
` return 0;`
`}
C++的异常处理机制并不完善,是否使用取决于开发团队的要求。