【C++】20.异常

news2024/10/7 16:19:03

1.C语言处理错误方式

  • 终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。
  • 返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码放到errno中,表示错误
  • C 标准库中setjmp和longjmp组合。这个不是很常用,了解一下

传统的处理错误的缺陷:

a.拿到错误码 需要查找错误码表 才知道是什么错误

b.如果一个函数使用过返回值拿数据 发生错误时很难处理

c.如果调用的函数栈很深 一层层返回错误码 整个处理很难受

2.C++异常

异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。

  1. throw: 当问题出现时,程序会抛出一个异常。这是通过使用 **throw **关键字来完成的。
  2. catch: 在您想要处理问题的地方,通过异常处理程序捕获异常 catch 关键字用于捕获异常,可以有多个catch进行捕获。
  3. try: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch 块。

3.异常的基本使用

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    try
    {
        vector<int> v = { 1,2,3,4,5 };
        for (int i = 0; i <= v.size(); ++i)
        {
            //cout << v[i] << " "; //越界就直接断言
            cout << v.at(i) << " ";//try+catch
        }
        cout << endl;
    }
    catch (exception& e)
    {
        cout << e.what() << endl;//what就是发生了什么错误
    }
    return 0;
}

4.异常的特性

异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。

被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。

首先检查throw本身是否在try块内部,如果是再查找匹配的catch语句。如果有匹配的,则调到catch的地方进行处理。

没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch。

如果到达main函数的栈,依旧没有匹配的,则终止程序。上述这个沿着调用链查找匹配的catch子句的过程称为栈展开。所以实际中我们最后都要加一个catch(...)捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止。

找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。

namespace szh
{
    //int div(int n, int m, int ret)
    //{
    //	//返回一个值区分不清楚 通过参数来拿
    //	if (m == 0)
    //	{
    //		return -1;	
    //	}

    //	//不好
    //	ret = n / m;
    //	return 0;
    //}
    int div(int n, int m)
    {
        //返回一个值区分不清楚 通过参数来拿
        if (m == 0)
        {
            //throw "发生除0错误"; //没有对应 程序会终止
            throw string("发生除0错误");//throw 可以抛出任意类型的对象
            //直接跳转到catch匹配的地方
            //先看f1有没有catch 再看main有没有catch
        }
        return n / m;
    }
}

void f1()
{
    try {
        int n, m;
        cin >> n >> m;
        cout << szh::div(n, m) << endl;
    }
    catch (const string& err)//类型匹配就会优先
    {
        cout << __LINE__ << " " << err << endl;
    }
}

int main()
{
    try
    {
        f1();
    }

    //捕捉列表可有多个
    catch (int err)
    {
        cout << err << endl;
    }

    catch (const string& err)
    {
        cout << __LINE__ << " " << err << endl;
    }

    catch (...) // 捕获没有匹配的任意类型的异常 避免异常没捕获时程序直接终止了
    {
        cout << "未知异常" << endl;
    }
}

要求你可以自己抛自己定义的异常 但是必须要继承这个基类

这样的话 外层捕获就只需要捕获基类就可以

class Exception
{
public:
    Exception(const char* errmsg,int errid)
        :_errmsg(errmsg)
        ,_errid(errid)
    {}

    virtual string what() = 0;//变为抽象类 强迫子类必须重写

protected:
    int _errid;           //错误码
    string _errmsg;       //错误描述
    //stack<string> _st;  //调用栈帧
};

class SqlException : public Exception
{
public:
    //子类构造函数调父类的
    SqlException(const char* errmsg, int errid)
        :Exception(errmsg,errid)
    {}
    virtual string what()
    {
        return "数据库错误:" + _errmsg;
    }
};

class NetworkException : public Exception
{
public:
    //子类构造函数调父类的
    NetworkException(const char* errmsg, int errid)
        :Exception(errmsg, errid)
    {}

    virtual string what()
    {
        return "网络错误:" + _errmsg;
    }
};

void ServerStart()
{
    //模拟一下出现问题抛异常报错
    if (rand() % 3 == 0)
        throw SqlException("数据库启动失败", 1);

    if (rand() % 7 == 0)
        throw NetworkException("网络连接失败", 3);

    cout << "正常运行" << endl;
}

int main()
{
    for (size_t i = 0; i < 10; ++i)
    {
        try
        {
            ServerStart();
        }

        catch (Exception& e)
        {
            cout << e.what() << endl;
        }

        catch (...)
        {
            cout << "未知异常" << endl;
        }
    }

    return 0;
}

5.异常安全

new/fopen func() delete/fclose

func()如果抛异常就会导致资源泄漏

所以有了异常规范

异常可能会导致异常安全问题

new/fopen/lock

func()//如果抛异常就会有异常安全问题 -> 解决:捕获重新抛出 or RAII解决

delete/fclose/unlock

函数规范一下 如果要抛异常 你说明清除 不抛异常也说明一下

但是现实中 很多人嫌麻烦 不遵守规范

这里表示这个函数会抛出A/B/C/D中的某种类型的异常 void fun() throw(A,B,C,D);

这里表示这个函数只会抛出bad_alloc的异常 void* operator new (std::size_t size) throw (std::bad_alloc);

这里表示这个函数不会抛出异常 void* operator new (std::size_t size, void* ptr) throw(); void* operator new (std::size_t size, void* ptr) noexcept;

  • 构造函数完成对象的构造和初始化,最好不要在构造函数中抛出异常,否则可能导致对象不完整或没有完全初始化。
  • 析构函数主要完成资源的清理,最好不要在析构函数内抛出异常,否则可能导致资源泄漏(内存泄漏、句柄未关闭等)

6.异常的优缺点

优点:

  1. 清晰的包含错误信息
  2. 面对T operator[](int i)这样函数越界错误 异常可以很好的解决
  3. 多层调用时 里面发生错误 不再需要层层处理 最外层直接捕获即可
  4. 很多第三方库都是用异常 我们也使用异常可以更好的配合 比如:boost/gtest/gmock

缺点:

  1. 异常会导致执行流乱跳 会给我们调试分析程序bug带来一些困难
  2. C++没有GC 异常可能导致资源泄漏等异常安全问题 需要学会使用RAII来解决
  3. C++的库里面的异常体系定义不太好用 很多公司都会选择自己定义
  4. C++的异常语法可以抛任意类型的异常 如果项目中没有做很好规范管理 那么会非常混乱 所以一般需要定义出继承体系的异常规范

异常整体而言还是一个利大于弊的东西 所以实际日常练习或者小项目 不太实用

公司一般还是会选择异常来处理错误

【C++】20.异常 完

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/531275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【003】C++数据类型之整型类型(int)详解

C数据类型之整型变量详解 引言一、常量和变量二、整形常量三、整形变量的定义四、整型变量的初始化五、整型变量的声明5.1、C 变量的定义、变量的声明、变量的使用三者的关系 六、键盘&#xff08;输入设备&#xff09;给变量赋值七、案例&#xff1a;键盘获取两个int数值然后求…

win11+VS2019下配置PCL1.11.1

1、PCL安装配置 下载pcl-1.11.1-pdb-msvc2019-win64与PCL-1.11.1-AllInOne-msvc2019-win64.exe文件。以管理员身份运行PCL-1.11.1-AllInOne-msvc2019-win64.exe程序&#xff0c;截图如下&#xff1a; 安装过程中没有弹出OpenNI2的安装&#xff0c;但是要安装在3rdParty下&#…

快速了解toRaw和markRaw的用法

toRaw toRaw&#xff0c;将响应式对象&#xff08;由 reactive定义的响应式&#xff09;转换为普通对象。 作用&#xff1a;将一个由reactive生成的响应式对象转为普通对象。使用场景&#xff1a;用于读取响应式对象对应的普通对象&#xff0c;对这个普通对象的所有操作&…

mongo基本操作---文档的增删改查

4、CRUD mongo数据库和平时常见的关系型数据库一样&#xff0c;最基本的操作就是增删改查&#xff0c;唯一的区别就是叫法不一样 SQL术语/概念MongoDB术语/概念解释/说明databasedatabase数据库tablecollection数据库表/集合rowdocument数据记录行/文档columnfield数据字段/域…

韦东山Linux驱动入门实验班(1)hello驱动

前言 &#xff08;1&#xff09;学习韦东山老师的Linux&#xff0c;因为他讲的很精简&#xff0c;以至于很多人听不懂。接下来我讲介绍韦东山老师的驱动实验班的第一个Hello程序。 &#xff08;2&#xff09;注意&#xff0c;请先学习完视频再来看这个教程&#xff01;本文仅供…

AD9680+JESD204B接口+FPGA FMC高速率数据采集板卡

板卡概述&#xff1a; 【FMC_XM155】 FMC_XM155 是一款基于 VITA57.1 标准的&#xff0c;实现 2 路 14-bit、500MSPS/1GSPS/1.25GSPS 直流耦合 ADC 同步采集 FMC 子卡模 块。 该模块遵循 VITA57.1 规范&#xff0c;可直接与 FPGA 载卡配合使用&#xff0c;板 卡 ADC 器件采用…

CIE颜色空间LCh、Lab、XYZ介绍与转换关系(包含源码)

项目场景&#xff1a; 提示&#xff1a;在颜色科学中&#xff0c;LCh和Lab是比较常用的 LCh是由MATLAB计算出的数据&#xff0c;但是我所需要在Qt的q3dsurface绘制出这个切面&#xff0c;看了Qt官方Examples&#xff0c;墨西哥草帽算法的3D模型就是由XYZ组成的。所以我需要LC…

【c语言】组件化打包—静态库

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c语言系列专栏&#xff1a;c语言之路重点知识整合 &#x…

MacOS使用Parallels Desktop安装win11虚拟机

文章目录 前话一、安装Parallels Desktop二、安装Windows11虚拟机1.win11镜像下载2.虚拟机启动 三、创建过程问题解决1.安装win11系统的时候不显示网路2.系统安装完成后无法连接网络 三、参考文献 前话 为了让大家能快速获取到需要的内容&#xff0c;这里提前说明一下本文适用…

杂记——23.java中的值传递和应用传递

这篇文章我们来讲一下java中的值传递和引用传递 结论&#xff1a;java中只存在值传递&#xff0c;不存在引用传递&#xff08;C中有引用传递&#xff09; 分析&#xff1a; 值传递(pass by value)&#xff1a;在调用函数时&#xff0c;将实际参数复制一份传递到函数中&#…

用DevExpress WinForms富文本编辑器,集成高级文本编辑功能(二)

DevExpress WinForm富文本编辑器&#xff08;RTF编辑器&#xff09;控件允许用户将高级文本编辑功能集成到下一个WinForms项目中&#xff0c;它包括全面的文本格式选项、支持邮件合并&#xff0c;并附带了丰富的终端用户选项集&#xff0c;因此可以轻松交付受Microsoft word启发…

助力工业物联网,工业大数据之数仓维度层DWS层构建【十二】

文章目录 数仓维度层DWS层构建01&#xff1a;项目回顾02&#xff1a;项目目标03&#xff1a;维度建模回顾&#xff1a;建模流程04&#xff1a;维度建模回顾&#xff1a;维度设计05&#xff1a;维度建模回顾&#xff1a;维度模型 数仓维度层DWS层构建 01&#xff1a;项目回顾 O…

《现代中学生》期刊简介及投稿要求

《现代中学生》期刊简介及投稿要求 《现代中学生》 主管单位&#xff1a;吉林省教育厅 主办单位&#xff1a; 吉林教育杂志社 国际刊号ISSN&#xff1a;1009-5748&#xff1b;国内刊号CN&#xff1a;22-1046/G4&#xff1b;邮发代号&#xff1a;12-52 出版周期&#xff1a…

刷题day65:整数拆分

题意描述&#xff1a; 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。. 思路&#xff1a; 首先dp[i]代表将i拆分&#xff0c;并得到的最大乘积&#xf…

springboot+jsp高校招生宣传系统java校园网站

学校招生管理系统的用户是系统最根本使用者&#xff0c;按需要分析系统包括两类用户&#xff1a;学生、管理员。这两类用户对系统的功能简要如下。 管理员通过后台的登录页面&#xff0c;选择管理员权限后进行登录&#xff0c;管理员的权限包括招生计划管理、招生录取信息管理和…

知识变现海哥:我们不生产知识,我们只是知识的搬运工!

现在大家都在谈知识付费&#xff0c;而且有一些东西就是书本上有的&#xff0c;但被录制成视频&#xff01;加上专业的讲师去讲&#xff0c;配上PPT文档&#xff0c;然后发布出去&#xff0c;标上一定的价格后&#xff0c;就会有人去付费购买学习。 想想是不是很暴利&#xff1…

如何使用ArcGIS生成随机数

&#xff08;本文首发于“水经注GIS”公号&#xff0c;关注公号免费领取地图数据&#xff09; 在制图的过程中&#xff0c;制作某些效果需要根据字段的随机数来生成对应的颜色&#xff0c;所以需要操作字段生成随机数&#xff0c;这里为大家介绍一下ArcGIS生成随机数的方法&…

对话金现代|轻骑兵低代码开发平台,破局企业“数字化焦虑

当今世界正经历百年未有之大变局&#xff0c;大数据、云计算、区块链、人工智能等新技术飞速发展&#xff0c;越来越多的企业经营者&#xff0c;开始投入到数字化转型的浪潮中&#xff0c;期望通过数字化帮助企业实现业务增长&#xff0c;开启无限可能。但随着时间的推移&#…

基于平台视角下的数据交易模式及特点分析

基于平台视角下的数据交易模式及特点分析 陈宏民1, 熊红林1, 胥莉1&#xff0c;杨云鹏1, 卓训方2 1 上海交通大学安泰经济与管理学院&#xff0c;上海 200030 2 上海数据交易所有限公司&#xff0c;上海 201203 摘要&#xff1a;基于国内外数据交易市场的发展现状与平台思维视角…

用GDB调试cmake编译后的C++程序

文章目录 编译时添加参数用GDB运行程序参考 编译时添加参数 cmake -DCMAKE_BUILD_TYPEDebug <path and other arguments>用GDB运行程序 开始调试 start设置断点&#xff0c;这样会在运行到源码第6行时停止&#xff0c;可以查看变量的值、堆栈情况等&#xff1b;这个行…