当前位置: 首页 > news >正文

C++(异常处理)

异常处理

1.概念:

异常是指程序在执行期间产生的问题,C++的异常是值在程序运行时发生的特殊情况,比如at函数的下标访问越界等。

2.特点:

(1)异常提供了一种转义控制权的方式。

控制权转移的本质:
当程序中发生异常时,它会中断当前的正常执行流程,将程序的控制权(即代码执行权)从当前点转移到专门处理错误的异常处理代码块。

(2)程序一旦出现异常没有经过处理,就会造成程序奔溃。

(3)异常的处理方式有两种,抛出异常(throw)捕获异常(try-catch)

2.抛出异常:

2.1 特点:

使用throw语句在代码块中任何地方都可以抛出异常。

throw语句的操作数可以是任意的表达式,表达式的结果决定了抛出异常的类型。

抛出的异常是抛出到函数调用的上一级。

2.2 自动抛出异常:

使用C++内置函数,在遇到一些错误情况会自动抛出异常错误,.at就是,如果越界就会抛出异常错误,上面那个图就是。

2.3 手动抛出异常:

设置string类型的异常信息test,当b是零的时候(被除数不能为零),a除以b不会计算,而是直接返回到上一级在division()位置抛出异常错误,如果后面没有对异常处理,就会继续返回上一级在iniput()位置抛出异常错误,如果还是无人处理就会程序崩溃,显示异常信息到终端。(不会显示设置的异常信息)

#include <iostream>using namespace std;double division(double a,double b){if(b == 0){//int test(0);string test("输入的第一个数是零");throw test;}return a/b;
}double input(){double a,b;cout << "输入除数和被除数:" << endl;cin >> a >> b;double c = division(a,b);        //第一个异常抛出,无人处理就会继续向上抛出异常cout << "结果是:" << c << endl;return c;
}int main (){cout << "程序开始" << endl;input();                    //第二次异常抛出位置,依旧无人处理,程序卡死cout << "程序结束" << endl;return 0;
}

3.捕获异常:

使用try去尝试运行可能会抛出错误的语句,然后在后面使用catch捕获try内语句可能抛出的异常。

3.1 解析:

上的程序在两个位置抛出了异常,我们在这两个位置都进行异常捕获,我们设置的异常信息是string类型的,但是我第一次尝试捕获的类型是double,捕获异常失败,会继续向上抛出异常,在第二次抛出异常的位置捕获string类型的异常,捕获成功,执行捕获到异常后的操作:先使用.what()打印异常信息,然后可以错误处理,退出当前函数体或者不写,不写就继续执行函数其他语句。

3.2 三种情况:

如果没有异常抛出,程序正常执行;

如果有异常抛出,正确捕获异常并且执行catch块;

如果有异常抛出,错误捕获异常,程序会继续向上抛出异常,如果每一层都没有正确捕获,程序仍然终止。

#include <iostream>using namespace std;double division(double &a,double &b){if(b == 0){//int test(0);string test("输入的第一个数是零");throw test;}return a/b;
}double input(){double a,b;cout << "输入除数和被除数:" << endl;cin >> a >> b;double c;try{c = division(a,b);        //尝试运行函数}catch(double &e){               //类型不匹配会捕获失败,向上抛出异常//打印错误信息cout << e << endl;//错误处理return 0;}cout << "结果是:" << c << endl;return c;
}int main (){cout << "程序开始" << endl;try{input();                    //尝试运行}catch(string &e){               //此处捕获成功成功cout << e << endl;return 0;}cout << "程序结束" << endl;return 0;
}

没有打印程序结束,因为最外层捕获到异常打印后直接退出程序了。 

4.标准异常体系

4.1 基础知识:

C++给常见的异常类型进行了定义和分类,引入头文件#include<stdexcept>后可以使用。

C++中这个体系比较薄弱,就是类型比较少,可以自行扩展。

自定义一个类型,继承某个异常类型后就可以使用,在C++中异常类型也是被做成类,然后继承出多个派生类来使用的。左边图中最上面的异常类型就死所有异常的基类,依次往后继承出多个派生类异常类型。

4.2 尝试捕获out_of_range标准异常

#include <iostream>
#include <stdexcept>using namespace std;int main (){cout << "程序开始" << endl;string s("hello");try{s.at(100);}catch(out_of_range &e){cout << e.what() << endl;}cout << "程序结束" << endl;return 0;
}

 这就是越界的时候,错误的详细信息,不捕获打印详细信息就只能看到上面的错误类型,还会使程序奔溃。正常处理完异常后还可以继续运行其他程序语句。

4.3 自定义类型异常

继承的是所有异常类型的基类,开创一个新的异常类型分支,然后重新定义异常信息。

#include <iostream>
#include <stdexcept>using namespace std;class MyEcepthion:public exception{
public:// 覆盖what函数// throw():异常规格说明// 表示此函数不会出现任何异常的抛出const char * what() const throw(){          //自定义类型异常return "自定义异常";}};int Mstrcmp(string a, string b){if(a == "1" || b == "1"){                   //输入字符串是1throw MyEcepthion();                    //抛出异常}return 0;
}int input(){string a;string b;cout << "输入两个字符串:" << endl;cin >> a >> b;try{Mstrcmp(a,b);}catch(MyEcepthion &e){                  //捕获异常cout << e.what() << endl;return 0;}return 1;
}int main (){cout << "程序开始" << endl;input();cout << "程序结束" << endl;return 0;
}

5.多重捕获

一个try块可以配合多个catch块同时匹配,因为一个catch块只能捕获一种类型错误信息,如果try内语句设置多中类型的异常,应该对多种异常都进行捕获。

#include <iostream>
#include <stdexcept>using namespace std;class MyEcepthion:public exception{
public:const char * what() const throw(){          //自定义类型异常return "自定义异常";}};int input(int type){try{if(type == 1){string a = "hello";cout << a.at(100) << endl;              //抛出越界异常}else if(type == 2){throw overflow_error("这是一个神奇的错误");      //抛出溢出错误}else{throw MyEcepthion();                //抛出自定义异常}}catch(out_of_range &e){                 //捕获越界异常cout << e.what() << endl;return 0;}catch(overflow_error &e){               //捕获溢出异常cout << e.what() << endl;return 0;}catch(MyEcepthion &e){                  //捕获自定义异常cout << e.what() << endl;return 0;}return 1;
}int main (){cout << "程序开始" << endl;int type;cin >> type;                    //输入类型input(type);cout << "程序结束" << endl;return 0;
}

输入1: 

输入2:

输入3: 

6.粗略捕获

6.1 粗略捕获标准异常

catch内捕获异常的类型设置为标准异常的基类,这样就可以捕获所有派生类异常,这提现了多态的性质,基类指针指向(引用)派生类对象)。 

特点:

越粗略的捕获所处位置越靠后,目的是捕获精确捕获没有捕获到的异常,防止程序崩溃。

#include <iostream>
#include <stdexcept>using namespace std;class MyEcepthion:public exception{
public:const char * what() const throw(){          //自定义类型异常return "自定义异常";}};int input(int type){try{if(type == 1){string a = "hello";cout << a.at(100) << endl;              //抛出越界异常}else if(type == 2){throw overflow_error("这是一个神奇的错误");      //抛出溢出错误}else{throw MyEcepthion();                //抛出自定义异常}}catch(out_of_range &e){                 //捕获越界异常cout << e.what() << endl;return 0;}/*catch(overflow_error &e){               //捕获溢出异常cout << e.what() << " 溢出异常" << endl;return 0;}*/catch(MyEcepthion &e){                  //捕获自定义异常cout << e.what() << endl;return 0;}catch(exception &e){                    //粗略捕获,类型2被注释掉,只能被粗略捕获cout << e.what() << "  粗略捕获" << endl;        return 0;}return 1;
}int main (){cout << "程序开始" << endl;int type;cin >> type;                    //输入类型input(type);cout << "程序结束" << endl;return 0;
}

6.2 捕获所有异常

可以使用...代替catch内的内容,表示捕获所以类型的异常,包括throw抛出的int等类型数据。

#include <iostream>
#include <stdexcept>using namespace std;class MyEcepthion:public exception{
public:const char * what() const throw(){          //自定义类型异常return "自定义异常";}};int input(int type){try{if(type == 1){string a = "hello";cout << a.at(100) << endl;              //抛出越界异常}else if(type == 2){throw overflow_error("这是一个神奇的错误");      //抛出溢出错误}else if(type == 3){throw MyEcepthion();                //抛出自定义异常}else{                                   //抛出int类型的数据throw 2;}}catch(out_of_range &e){                 //捕获越界异常cout << e.what() << endl;return 0;}/*catch(overflow_error &e){               //捕获溢出异常cout << e.what() << " 溢出异常" << endl;return 0;}*/catch(MyEcepthion &e){                  //捕获自定义异常cout << e.what() << endl;return 0;}catch(exception &e){                    //粗略捕获cout << e.what() << "  粗略捕获" << endl;return 0;}catch(...){                                 //最后收尾,捕获所有类型异常,包括数据cout << "捕获全部异常" << endl;}return 1;
}int main (){cout << "程序开始" << endl;int type;cin >> type;                    //输入类型input(type);cout << "程序结束" << endl;return 0;
}

相关文章:

  • 网页制作软件 苹果竞价推广和seo的区别
  • 盐城网站建设找哪家好网站友链
  • 哪一个景区网站做的最成熟微信朋友圈广告
  • 广州网站定制服务seo外包公司费用
  • 做玻璃钢的企业网站cps推广
  • 在线图片编辑源码广东seo推广公司
  • 电影交流平台小程序完整项目
  • 鸿蒙OH南向开发 轻量系统内核(LiteOS-M)【异常调测】
  • linux操作系统的软件架构分析
  • 左神算法之双集合平均值优化操作的最大次数
  • 【Linux】高级IO
  • MySQL:深入总结锁机制
  • 机器学习×第十四卷:集成学习中篇——她从每次错误中修正自己
  • Java实现简易即时通讯系统
  • Linux离线搭建Jenkins
  • C++【生存游戏】开发:荒岛往事 第一期
  • GLib库介绍与linux下应用
  • 基于元学习的回归预测模型如何设计?
  • ubuntu20.04安装多版本python时,如何使用sudo python3.10
  • Linux系统---Nginx配置nginx状态统计
  • 如何使用MQTTX软件来进行MQTT协议的测试
  • Harmony状态管理 @Local和@Param
  • 计算机网络期末复习
  • Git 3天2K星标: Happy-LLM 项目介绍(附教程)
  • 【基础篇-消息队列】—— 如何实现单个队列的并行消费及如何保证消息的严格顺序
  • LangChain网页自动化PlayWrightBrowserToolkit