嵌入式学习-C嘎嘎-Day06

嵌入式学习-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++的异常处理机制并不完善,是否使用取决于开发团队的要求。

相关推荐
dialect_5 分钟前
KMP算法
开发语言·c++·算法
总要学点什么1 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
ShineWinsu2 小时前
对于Qt:QRadioButton常见属性以及QButtonGroup的解析
数据库·c++·qt·microsoft·gui·qradiobutton·qbuttongroup
傲世仙尊2 小时前
多态-虚表才活到运行期符号表早已消失
c++
开开心心_Every2 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
chenbingjie_c2 小时前
C++ 多态完全指南:从虚函数重写到虚函数表原理
开发语言·c++
是main不是漫2 小时前
【双指针——移动零】数组划分类题目的入门基石
c++·算法
Nuanyt3 小时前
Agent 学习笔记(下篇三):上线工程、进阶选择与操作界面(Stage 7 / 7.5 / 8 + 延伸路线)
笔记·python·学习·memory·aiagent·harness
吴卫斌3 小时前
定投ETF实战指南(四):行业/主题ETF——定投的“进攻端“
开发语言·python·股票·量化
·present·3 小时前
CSAPP(Bomb lab)
c语言·c++