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

【C++进阶9】异常

在这里插入图片描述

一、C语言传统的处理错误的方式

  1. 终止程序,如assert
    如发生内存错误,除0错误时就会终止程序
  2. 返回错误码
    需要程序员自己去查找对应的错误
    z如系统的很多库的接口函数都是通
    过把错误码放到errno中,表示错误

二、C++异常概念

异常:函数无法处理的错误就可以抛出异常
让函数的直接或间接的调用者处理这个错误

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

使用方法

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0)throw "Division by zero condition!";elsereturn ((double)a / (double)b);
}
void Func()
{int len, time;cin >> len >> time;cout << Division(len, time) << endl;
}int main()
{try{Func();}catch (const char* str) // catch 得跟"Division by zero condition!"类型匹配{cout << str << endl; // Division by zero condition!}return 0;
}

2.1 异常的抛出和匹配原则

  1. 异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码
  2. 选中的处理代码是调用链中与该对象类型匹配离抛出异常位置最近的那一个
  3. 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,
    所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁
    (这里的处理类似于函数的传值返回)
  4. catch(…)可以捕获任意类型的异常,问题是不知道异常错误是什么
  5. 实际中抛出和捕获的匹配原则有个例外,并不都是类型完全匹配,可以抛出的派生类对象,使用基类捕获,这个在实际中非常实用

正常的异常抛出包含
错误码和错误描述

class Exception
{
public:Exception(int errid, const string& msg): _errid(errid), _errmsg(msg){}const string& GetMsg() const // 引用返回,成员变量出了作用域还在{return _errmsg;}int GetErrid() const{return _errid;}private:int _errid; // 错误码string _errmsg; // 错误描述
};double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0){// Exception err(1, "除0错误");// throw err;throw Exception(1, "除0错误"); // 用匿名对象,连续的构造+拷贝编译器会优化}else{return ((double)a / (double)b);}
}void Func()
{int len, time;cin >> len >> time;try {cout << Division(len, time) << endl;}catch (char str){cout << str << endl;}cout << "void Func()" << endl;
}int main()
{try{Func();}catch (const Exception& e) {cout << e.GetMsg() << endl;}catch (...) // 捕获任意类型的异常,一般放到最后,防止有些异常没捕获到,导致程序终止{cout << "未知异常" << endl; }return 0;
}

一个公司里面每个人对抛异常的需求不一样
有些人可能只需要一个错误码
有些人则需要更详细的信息

解决方法: 可以搞一个继承体系
比如你是缓存部分我是网络部分
可以写一个子类继承父类Exception
捕获的时候捕两个部分
一个Exception
一个是未知异常
C++很灵活的地方抛子类捕父类

三、自定义异常体系

实际使用中很多公司
都会自定义自己的异常体系
进行规范的异常管理
因为一个项目
如果大家随意抛异常
那么外层的调用者基本没法玩
所以实际中会定义一套继承的规范体系
这样大家抛出的都是继承的派生类对象
捕获一个基类就可以了
在这里插入图片描述
服务器开发中通常使用的异常继承体系

class Exception
{
public:Exception(int errid, const string& msg): _errid(errid), _errmsg(msg){}virtual string what() const // 引用返回,成员变量出了作用域还在{return _errmsg;}int GetErrid() const{return _errid;}protected: // 子类可见用保护int _errid; // 错误码string _errmsg; // 错误描述
};class SqlException : Exception // sql专属继承
{
public:SqlException(int errid, const string& msg, const string& sql) // 派生类必须调用父类的构造函数,派生类的特点必须得去复用父类: Exception(errid, msg), _sql(sql){}virtual string what() const // exception写成虚函数进行重写,构造需要的错误信息进行返回{string msg = "SqlException:";msg += _errmsg;msg += "->";msg += _sql;return msg;}protected:string _sql;
};// 出现数据库错误或网络错误
class CacheException : public Exception
{
public:CacheException(const string& errmsg, int id):Exception(id, errmsg){}virtual string what() const{string msg = "CacheException:";msg += _errmsg;return msg;}
};class HttpServerException : public Exception
{
public:HttpServerException(const string& errmsg, int id, const string& type) // 外加一个类型错误:Exception(id, errmsg), _type(type){}virtual string what() const{string msg = "HttpServerException:";msg += _errmsg;msg += "->";msg += _type; return msg;}private:const string _type;
};void SQLMgr() // 数据库
{srand(time(0));if (rand() % 7 == 0){throw SqlException(100, "权限不足", "select * from name = '张三'");}cout << "调用成功" << endl; // 3.数据库出错抛异常,数据库没出错,调用成功.数据库取到数据进行返回 
}void CacheMgr() // 缓存
{srand(time(0));if (rand() % 5 == 0){throw CacheException("权限不足", 100);}else if (rand() % 6 == 0){throw CacheException("数据不存在", 101);}SQLMgr(); // 2.缓存出错抛异常,没出错调用数据库
}void HttpServer() // 网络
{// 模拟服务出错srand(time(0));if (rand() % 3 == 0){throw HttpServerException("请求资源不存在", 100, "get");}else if (rand() % 4 == 0){throw HttpServerException("权限不足", 101, "post");}CacheMgr(); // 1.网络出错抛异常,没出错调用缓存
}int main()
{while (1){this_thread::sleep_for(chrono::seconds(1));try {HttpServer();}//catch (const HttpServerException& e) // 当子类和父类同时出现,按顺序走,优先匹配位置近的//{//	cout << "子类";//	cout << e.what() << endl;//}catch (const Exception& e) // 这里捕获父类对象就可以{// 通过多态拿错误信息.多态指向子类,通过调用子类拿到错误信息 cout << e.what() << endl; // e是父类对象,抛的可能是父类,调的就是父类的what.抛的如果是sql,指向的是子类,调what调用的则是子类的what}catch (...){cout << "Unkown Exception" << endl; // 捕捉未知异常}}return 0;
}

3.1 异常的重新抛出

有可能单个catch不能完全处理一个异常
在进行一些校正处理以后,希望再交给更外层的调用
链函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0){throw "Division by zero condition!";}return (double)a / (double)b;
}void Func()
{// 这里可以看到如果发生除0错误抛出异常,另外下面的array没有得到释放。// 所以这里捕获异常后并不处理异常,异常还是交给外面处理,这里捕获了再// 重新抛出去。int* array = new int[10]; // 如果抛异常会发生内存泄漏int len, time;cin >> len >> time;try // 所以捕获异常{cout << Division(len, time) << endl;}/*catch (const char* errmsg){cout << errmsg << endl;}*///catch (const char* errmsg)//{//	cout << "delete []" << array << endl; //	delete[] array;//	throw errmsg; // 重新抛出异常,抛之前释放一下//}catch (...) // 各种抛错异常,需要不同的捕获方法,用...便可一劳永逸{cout << "delete []" << array << endl; delete[] array;throw; // 异常的重新抛出,捕到什么抛什么}cout << "delete []" << array << endl; // 如果期望在main函数执行异常,且能够继续完成释放,这是就可以用异常的重新抛出delete[] array;
}int main()
{try{Func();}catch (const char* errmsg){cout << errmsg << endl;}return 0;
}

需要注意的是:
构造函数完成对象的构造和初始化
不要在构造函数中抛出异常
否则可能导致对象不完整
或没有完全初始化

析构函数主要完成资源的清理
不要在析构函数内抛出异常
否则可能导致资源泄漏

C++中异常经常导致资源泄漏的问题
比如:
在new和delete中抛出异常导致内存泄漏
在lock和unlock之间抛出异常导致死锁
C++经常使用RAII来解决以上问题
而RAII在下一篇博客智能指针
会进行专门讲解

在这里插入图片描述
本篇博客完,感谢阅读🌹
如有错误之处可评论指出
博主会耐心听取每条意见

相关文章:

【C++进阶9】异常

一、C语言传统的处理错误的方式 终止程序&#xff0c;如assert 如发生内存错误&#xff0c;除0错误时就会终止程序返回错误码 需要程序员自己去查找对应的错误 z如系统的很多库的接口函数都是通 过把错误码放到errno中&#xff0c;表示错误 二、C异常概念 异常&#xff1a;函…...

RecyclerVIew->加速再减速的RecyclerVIew平滑对齐工具类SnapHelper

XML文件 ItemView的XML文件R.layout.shape_item_view <?xml version"1.0" encoding"utf-8"?> <FrameLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"100dp"android:layout_heig…...

突破SaaS产品运营困境:多渠道运营如何集中管理?

随着数字化时代的到来&#xff0c;SaaS&#xff08;软件即服务&#xff09;产品已成为企业日常运营不可或缺的工具。然而&#xff0c;在竞争激烈的市场环境下&#xff0c;SaaS产品运营越来越重视多渠道、多平台布局&#xff0c;以更广泛地触及潜在用户&#xff0c;然而&#xf…...

智能语音热水器:置入NRK3301离线语音识别ic 迈向智能家居新时代

一、热水器语音识别芯片开发背景 在科技的今天&#xff0c;人们对于生活品质的追求已不仅仅满足于基本的物质需求&#xff0c;更渴望通过智能技术让生活变得更加便捷、舒适。热水器作为家庭生活中不可或缺的一部分&#xff0c;其智能化转型势在必行。 在传统热水器使用中&#…...

Redis集群部署合集

目录 一. 原理简述 二. 集群配置​​​​​​​ 2.1 环境准备 2.2 编译安装一个redis 2.3 创建集群 2.4 写入数据测试 实验一&#xff1a; 实验二&#xff1a; 实验三&#xff1a; 实验四&#xff1a; 添加节点 自动分配槽位 提升节点为master&#xff1a; 实验…...

【HDFS】关于Hadoop的IPC.Client类的一些整理

org.apache.hadoop.ipc.Client 类是IPC服务的一个客户端。 IPC请求把一个Writable对象当做参数,返回一个Writable对象当做结果value。 一个IPC服务运行在某个端口上,并且由参数class和value class定义。 Router里的IPC.Client对象就两个 有这样一个类:ClientCache 看名字就…...

Swoole v6 能否让 PHP 再次伟大?

现状 传统的 PHP-FPM 也是多进程模型的的运行方式&#xff0c;但每个进程只能处理完当前请求&#xff0c;才能接收下一个请求。而且对于 PHP 脚本来说&#xff0c;只是接收请求和响应请求&#xff0c;并不参与网络通信。对数据库资源的操作&#xff0c;也是一次请求一次有效&am…...

C++ STL Iterator Adapter

1. std::back_insert_iterator 使用 // back_insert_iterator example #include <iostream> // std::cout #include <iterator> // std::back_insert_iterator #include <vector> // std::vector #include <algorithm> // std::copy…...

android-aidl5

aidl类是实现Manager和Service通信的桥梁。 例如在修改Android Wifi功能的时候看到WifiManager管理WifiService&#xff1b; AIDL是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。 比如onclick&#xff08;&#xff09;&#xff0c;用oneway修…...

day01-项目介绍及初始化-登录页

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 day01-项目介绍及初始化-登录页一、人力资源项目介绍1.1项目架构和解决方案主要模块解决的问题 二、拉取项目基础代码1.引入库2.升级core-js版本到3.25.5按照完整依…...

华为开发者大会:全场景智能操作系统HarmonyOS NEXT

文章目录 一、全场景智能操作系统 - HarmonyOS NEXT1.1 系统特性1.2 关于架构、体验和生态 二、应用案例2.1 蚂蚁mpaas平台的性能表现 三、新版本应用框架发布3.1 新语言发布3.2 新数据库发布3.3 新版本编译器的发布 四、CodeArts和DataArts4.1 CodeArts4.2 DataArts 五、总结 …...

深度学习二分类评估详细解析与代码实战

深度学习二分类的实战代码&#xff1a;使用 Trainer API 微调模型. https://huggingface.co/learn/nlp-course/zh-CN/chapter3/3 如果你刚接触 自然语言处理&#xff0c;huggingface 是你绕不过去的坎。但是目前它已经被墙了&#xff0c;相信读者的实力&#xff0c;自行解决吧。…...

c++笔记容器详细介绍

C标准库提供了多种容器来存储和管理数据。这些容器属于<vector>, <list>, <deque>, <map>, <set>, <unordered_map>, <unordered_set>等头文件中。这些容器各有优缺点&#xff0c;适用于不同的场景。下面详细介绍几种主要的容器及其…...

CS144 Lab3 TCPSender复盘

一.基础概念 1.TCPSender在TCPSocket中的地位与作用 Lab0中实现了基于内存模拟的流控制-字节流&#xff08;ByteStream&#xff09;&#xff0c;底层使用std::deque实现&#xff0c;根据最大容量Capacity进行容量控制。个人理解它相当于应用层的输入输出缓存区&#xff0c;用户…...

建筑可视化中使用云渲染的几大理由

在建筑行业中&#xff0c;可视化技术已成为不可或缺的一部分。无论是设计方案的展示、施工进度的模拟&#xff0c;还是最终效果的呈现&#xff0c;建筑可视化都发挥着至关重要的作用。 建筑可视化是指通过计算机技术和图形学算法&#xff0c;将建筑设计、规划和施工过程中的数据…...

Python数据可视化-地图可视化

1.首先绘制实现数据可视化的思维导图 具体要实现什么功能-怎么处理&#xff0c;先把思路写好 数据来源&#xff1a; 爬取的数据 运行结果&#xff1a; 部分代码&#xff1a; 完整代码请在下方↓↓↓&#x1f447;获取 转载请注明出处&#xff01;...

leetcode 动态规划(基础版)单词拆分

题目&#xff1a; 题解&#xff1a; 一种可行的dp做法是基于完全背包问题&#xff0c;将s看成是一个背包&#xff0c;wordDict看作是物品&#xff0c;然后往s中放入物品判断最终是否可以变为给定的s即可。这道题和上一题都用到了在dp如何枚举连续子串和状态表示&#xff1a;枚…...

Ubuntu/Linux调试安装南京来可CAN卡

准备好USB rules文件和can driver文件备用! 必做&#xff1a;放置USB rules文件到对应位置处理权限问题 而后&#xff1a;安装内核driver并编译。需求众多依赖编译环境&#xff0c;视情况安装填补。如GCC,G,make等等 进入对应64bit文件夹中&#xff0c;添加权限&#xff0c;执…...

vue2+TS获取到数据后自动叫号写法

1.父组件写法 初始化&#xff1a; //引入子组件 <odialog ref"odialogRef" onSure"onSurea"></odialog> //子传父private onSurea() {// 初始化信息/重新叫号来的数据this.initTabelData()setTimeout(() > {// 播放声音的数据this.search…...

28、架构-边界:微服务的粒度

微服务的粒度 在设计微服务架构时&#xff0c;确定微服务的粒度是一个关键问题。粒度过大或过小都会带来不同的问题&#xff0c;因此需要找到合理的粒度来划分微服务。下面详细探讨微服务粒度的合理范围及其影响因素。 1. 微服务粒度的上下界 微服务的粒度不应该只有唯一正确…...

开源API网关-ApacheShenYu首次按照启动遇到的问题

一.背景 公司有API网关产品需求&#xff0c;希望有图形化的后台管理功能。看到了ApacheShenYu&#xff0c;作为Apache的顶级项目&#xff0c;直接认可了。首先&#xff0c;感谢各位大神的付出&#xff0c;初步看这个项目是国内大厂中的大神创立的&#xff0c;在此表示膜拜&…...

uniapp获取证书秘钥、Android App备案获取公钥、签名MD5值

一、 uniapp获取证书秘钥 打开uniapp开发者中心下载证书打开cmd输入以下这段代码&#xff0c;下载提供查看到的密钥证书密码就可以了&#xff01;下载证书在 java 环境下运行才可以 // your_alias 换成 证书详情中的别名&#xff0c;your_keystore.keystore 改成自己的证书文件…...

QT 如何储存多种数据类型(QVariant )

QVariant 是 Qt 框架中用于存储各种数据类型的类。它提供了一个强大的类型系统&#xff0c;允许你在运行时存储和检索多种类型的数据&#xff0c;而不需要在编译时确定类型。QVariant 的主要优点在于它的灵活性和通用性&#xff0c;这使得它在 Qt 的很多组件和机制中都被广泛使…...

持续总结中!2024年面试必问的操作系统面试题(九)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问的操作系统面试题&#xff08;八&#xff09;-CSDN博客 十七、解释什么是操作系统的安全性和它的重要性。 操作系统的安全性&#xff08;Operating System Security&#xff09;是指操作系统采取的一系列措施来保…...

操作系统入门 -- 文件管理

操作系统入门 – 文件管理 1.文件管理概述 1.1 文件系统基本功能 目前&#xff0c;计算机内存的容量依然有限&#xff0c;并且其特性决定了数据无法长时间保存&#xff0c;因此把执行的数据以文件形式保存在外存中&#xff0c;等到需要使用时再调入内存。所以&#xff0c;操…...

由浅入深,走进深度学习(2)

今天分享的学习内容主要就是神经网络里面的知识啦&#xff0c;用到的框架就是torch 在这里我也是对自己做一个学习记录&#xff0c;如果不符合大家的口味&#xff0c;大家划走就可以啦 可能没有什么文字或者原理上的讲解&#xff0c;基本上都是代码&#xff0c;但是我还是想说…...

【Python Tips】创建自己的函数包并安装进Anaconda,像引入标准包一样直接import导入

目录 一、引言 二、方法步骤 步骤一&#xff1a;创建包目录结构 步骤二&#xff1a;配置__init__.py文件 步骤三&#xff1a;文件夹外配置setup.py文件 步骤四&#xff1a;终端Pip安装 三、结尾 一、引言 在编写项目代码的时候&#xff0c;有些自定义功能的函数是可以复用的。…...

【Python机器学习实战】 | 基于支持向量机(Support Vector Machine, SVM)进行分类和回归任务分析

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…...

备份和还原

stai和dnta snat&#xff1a;源地址转换 内网---外网 内网ip转换成可以访问外网的ip 内网的多个主机可以使用一个有效的公网ip地址访问外部网络 DNAT&#xff1a;目的地址转发 外部用户&#xff0c;可以通过一个公网地址访问服务内部的私网服务。 私网的ip和公网ip做一个…...

Java数组的初始化方法

Java数组的初始化方法 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在Java编程中&#xff0c;数组是一种非常基础也非常重要的数据结构&#xff0c;它能够存储…...

湖南网站建设企业/关键词优化师

const readline require(readline-sync);//引入用户输入功能console.log(请输入数组的长度&#xff1a;);//提示用户输入let length readline.question();//获取用户输入let arr [];//创建数组for (let i 0; i < length; i) {console.log(请输入数组的第${i 1}个数&…...

微信可以做网站吗/全国最新的疫情数据

Excel&#xff1a;常见的错误信息以及解决方法(转)在Excel中建立了一张工作表&#xff0c;往往希望所有数据都是正确的。但是&#xff0c;基本上这是不可能的&#xff01;而偏偏计算机是个“较真”的家伙&#xff0c;如果你不改正错误&#xff0c;它会就此罢工&#xff0c;不再…...

遵义在线/重庆镇海seo整站优化价格

框架可以简化操作&#xff0c;提高代码利用率&#xff0c;jdbc方式还有很多欠缺&#xff0c;因此不是框架所需要的&#xff0c;于是springjpa挺身而出&#xff0c;它不仅有springjdbc的集成性&#xff0c;而且具有简化sql&#xff0c;实现分页等等比较常用的功能。 其实现类似于…...

快速做网站服务好/2023智慧树网络营销答案

数据库批处理 批处理(batch)指的是一次操作中执行多条SQL语句&#xff0c;批处理相比于一次一次执行效率会提高很多。 批处理操作数据库的过程主要是分两步&#xff1a; 将要执行的SQL语句保存执行保存的SQL语句 如何实现批处理 Statement和PreparedStatement都支持批处理操…...

wordpress评论推广/太原优化排名推广

模板介绍 医疗保健服务宣传和医疗咨询服务PPT模板-优页文档。一套,疫情防护,幻灯片模板&#xff0c;内含青色,蓝色多种配色&#xff0c;风格设计&#xff0c;动态播放效果&#xff0c;精美实用。 希望下面这份精美的PPT模板能给你带来帮助&#xff0c;温馨提示&#xff1a;本…...

石家庄建网站挣钱优帮云/湖南网络推广机构

理解Session可以从其名称入手&#xff0c;翻译成汉语具有"会话"的意思。所谓的会话是一段有始有终的交互操作&#xff0c;比如通过手机与朋友进行语音通话。特别说明&#xff1a;Session与sessionStorage并无联系&#xff0c;只因名称有所关联所以做一下介绍。一.HTT…...