C++:异常

---什么是异常?
异常是面向对象语法处理错误的一种方式。

---C语言传统的处理错误的方式有哪些呢?
1.返回错误码,有些API接口都是把错误码放到errno中。
2.终止程序,比如发生越界等严重问题时,我们也可以主动调用exit(xx)。例如:exit(-1)

---传统的处理错误的缺陷:
a.拿到错误码,需要查找错误码表,才知道是什么错误。
b.如果一个函数是用过返回值拿数据,发生错误时很难处理。

T& operator[](int index)//[]下标运算符不会做越界访问保护
{如果index超出容器范围,如何返回?
}

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

int f1()
{//.....发生错误,返回错误码
}
int f2()
{f1();
}
int f3()
{f2();
}

---面对上面问题,C++用异常来解决: 

int x1()//基本使用
{try//检查代码段{vector<int> v = { 1,2,3,4,5,6 };for (int i = 0; i < v.size(); ++i){cout << v.at(i) << " ";//越界访问,抛出异常}cout << endl;}catch (exception& e)//捕获异常,进行处理并输出{cout << e.what() << endl;}return 0;
}

在这里需要了解vector类中,operator [] 下标运算符不会做越界访问保护,不会检查是否越界也不会抛出异常;而at()会进行越界检查,如果越界会抛出out of range的异常,此时我们用try语句来检测它是否抛出异常,并且用catch语句去捕获异常处理它。

---a.需要注意的是,在C++语法中,throw语句抛出的异常是用户自定义的,可以是任意类型。

int ddiv(int n, int m)
{//if (m == 0) throw - 1;//throw可以抛出任意类型的对象if (m == 0){throw "除0异常";//临时拷贝对象,}//可以throw整型/字符串...任意类型return n / m;
}

---b. try语句检测到异常,交给catch语句来捕获处理,是会调用最近的catch语句。

int ff()
{int n, m;cin >> n >> m;try//调用最近的catch{cout << ddiv(n, m) << endl;}catch (const string& x)//会优先调用ff函数内的catch语句{cout << x << endl;}
}
int main()
{try{ff();}catch (const string& x){cout << x << endl;}
}

---c.有多种的catch语句来捕获抛出的不同类型的异常。

int main()
{try{ff();}catch (int x)//捕获抛出的整型异常{cout << x << endl;}catch (const string& x)//捕获抛出的字符串异常{cout << x << endl;}catch (...)//捕获所有类型的异常{cout << "其它异常" << endl;}
}

---C++异常中需要注意的问题: 

---a.throw抛出的异常被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];try {int len, time;cin >> len >> time;cout << Division(len, time) << endl;}catch (...){cout << "delete []" << array << endl;delete[] array;throw;}// ...cout << "delete []" << array << endl;delete[] array;
}

--- b.由于throw可以抛出各种各样的异常,这样就得有各种各样的catch语句去捕获。容易造成混乱,可以通过throw派生类,catch基类--Exception来规范异常处理:你可以自己抛自己的异常,但是必须继承这个基类,但是外层捕获基类就可以。

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){}string what(){return "数据库错误:" + _errmsg;}
};
class Network :public Exception
{
public:Network(const char* errmsg, int errid):Exception(errmsg,errid){}string what(){return "网络错误:" + _errmsg;}
};
void ser()
{//模拟一下出现问题抛异常报错if (rand() % 3 == 0) throw SqlException("数据库启动失败", 1);if (rand() % 7 == 0) throw Network("网络连接失败失败", 3);
}
int main()
{for (size_t i = 0; i < 100; ++i){try{ser();}catch (Exception& e)//用父类对象捕获,抛出的是匿名子类对象,并实现多态->父类对象指向的是子类对象{cout << "未知异常" << endl;}}return 0;
}

---c.异常破坏程序执行流所引发的问题: 

//异常带来的问题:new/fopen/lock --func()在此处抛异常-- delete/fclose
//异常规范:异常可能会导致异常安全问题--捕获重新抛出/RAII解决
//函数规范一下,如果抛异常说明,不抛也说明;但是现实中很多人觉得麻烦,不遵守规范,并不实用。
// 这里表示这个函数会抛出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 delete (std::size_t size, void* ptr) throw();
// C++11 中新增的noexcept,表示不会抛异常
thread() noexcept;
thread(thread&& x) noexcept;

---C++的异常体系:
C++ 提供了一系列标准的异常,定义在库中,我们可以在程序中使用这些标准的异常。它们是以父 子类层次结构组织起来的,如下所示:
 

总结: 
---优点:
//1.清晰的包含错误
//2.面对 T operator[](int i)这样函数越界错误,异常可以很好的解决
//3.多层调用时,里面发生错误,不再需要层层处理,最外层直接捕获即可
//4.很多第三方库使用异常,我们也使用异常可以更好的使用他们。比如:boost\gtest\gmock
---缺点:
//1.异常会导致执行流乱跳。会给我们分析程序Bug带来一些困难。
//2.C++没有GC(资源回收),异常可能导致资源泄露等异常安全问题。需要学会使用RAII来解决。
//3.C++的库里面的异常体系定义不太好用,很多公司会选择自己定义。
//4.C++的异常语言可以抛任意类型的异常,如果项目中没有做很好的规范管理,会非常混乱,所以一般需要定义出继承体系的异常规范。
异常整体而言还是一个利大于弊的东西,所以实际日常练习或小项目,不太使用,公司一般还是会使用异常来处理错误。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年MathorCup高校数学建模挑战赛—大数据竞赛B题电商零售商家需求预测及库存优化问题求解全过程文档及程序

2023年MathorCup高校数学建模挑战赛—大数据竞赛 B题 电商零售商家需求预测及库存优化问题 原题再现&#xff1a; 电商平台存在着上千个商家&#xff0c;他们会将商品货物放在电商配套的仓库&#xff0c;电商平台会对这些货物进行统一管理。通过科学的管理手段和智能决策&…

前端node.js

一.什么是node.js 官网解释:Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。 二.初步使用node.js 需要区分开的是node.js和javascript互通的只有console和定时器两个API. 三.Buffer Buffer 是一个类似于数组的 对象&#xff0c;用于表示固定长度的字节序列。Buffer…

偏差-方差权衡(Bias–Variance Tradeoff):理解监督学习中的核心问题

偏差-方差权衡&#xff08;Bias–Variance Tradeoff&#xff09;&#xff1a;理解监督学习中的核心问题 在机器学习中&#xff0c;我们希望构建一个能够在训练数据上表现良好&#xff0c;同时对未见数据也具有强大泛化能力的模型。然而&#xff0c;模型的误差&#xff08;尤其…

go-zero使用自定义模板实现统一格式的 body 响应

前提 go环境的配置、goctl的安装、go-zero的基本使用默认都会 需求 go-zero框架中&#xff0c;默认使用goctl命令生成的代码并没有统一响应格式&#xff0c;现在使用自定义模板实现统一响应格式&#xff1a; {"code": 0,"msg": "OK","d…

Matlab热力图巅峰之作

准备‘data.xlsx’ 的热力图文件&#xff1a; main&#xff1a; clc; clear; close all; % 相关性气泡热图%% 数据准备 % 读取Excel文件数据 data readmatrix(data.xlsx); % 读取Excel文件中的数据%% 颜色定义 map colormap("cool"); map map([2:6,9:13],1:3)…

时序论文28|CycleNet:通过对周期模式进行建模增强时间序列预测

论文标题&#xff1a;CycleNet: Enhancing Time Series Forecasting through Modeling Periodic Patterns 论文链接&#xff1a;https://arxiv.org/abs/2409.18479v1 代码链接&#xff1a;https://github.com/ACAT-SCUT/CycleNet 前言 这是今年NIPS的一篇时序论文&#xff…

自动化运维(k8s)之微服务信息自动抓取:namespaceName、deploymentName等全解析

前言&#xff1a;公司云原生k8s二开工程师发了一串通用性命令用来查询以下数值&#xff0c;我想着能不能将这命令写成一个自动化脚本。 起初设计的 版本一&#xff1a;开头加一条环境变量&#xff0c;执行脚本后&#xff0c;提示输入&#xff1a;需要查询的命名空间&#xff0c…

如何把产品3D模型放到网站上进行3D展示或3D互动?

要将产品3D模型放到网站上进行3D展示或3D互动&#xff0c;可以按照以下步骤进行&#xff1a; 一、准备3D模型 使用3D建模软件&#xff08;如3ds Max、Maya、Blender、C4D等&#xff09;制作好产品的3D模型。 确保3D模型的格式是网站或平台所支持的&#xff0c;常见的格式包括…

ESP32驱动PCM5102A播放SD卡音频

文章目录 简介模块参数功能框图引脚定义通信接口和通信数据格式通信流程引脚接线ESP32和PCM5102AESP32和SD模块 主要代码spi.hSD.hAudio.h实验效果总结 简介 PCM5102A模块是一款立体声DAC模块、音频数模转换器&#xff0c;内部集成了PCM5102芯片。PCM5102芯片是集成了立体声模…

【人工智能】Python常用库-TensorFlow常用方法教程

TensorFlow 是一个广泛应用的开源深度学习框架&#xff0c;支持多种机器学习任务&#xff0c;如深度学习、神经网络、强化学习等。以下是 TensorFlow 的详细教程&#xff0c;涵盖基础使用方法和示例代码。 1. 安装与导入 安装 TensorFlow&#xff1a; pip install tensorflow…

【设计模式系列】解释器模式(十七)

一、什么是解释器模式 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为型设计模式&#xff0c;它的核心思想是分离实现与解释执行。它用于定义语言的文法规则&#xff0c;并解释执行语言中的表达式。这种模式通常是将每个表达式抽象成一个类&#xff0c;并通…

【查询目录】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

设计模式:11、迭代器模式(游标)

目录 0、定义 1、迭代器模式的四种角色 2、迭代器模式的UML类图 3、示例代码 4、迭代器的next()方法与集合的get(int index)方法的效率对比&#xff08;LinkedList为例&#xff09; 0、定义 提供一种方法顺序访问一个聚合对象中的各个元素&#xff0c;而又不需要暴露该对象…

Web开发基础学习——通过React示例学习模态对话框

Web开发基础学习系列文章目录 第一章 基础知识学习之通过React组件学习模态对话框 文章目录 Web开发基础学习系列文章目录前言一、创建新的 React 应用二、 创建模态对话框组件三、修改 App.js四、 添加样式五、启动应用六、访问应用总结 前言 模态对话框&#xff08;Modal D…

Unity XR Interaction Toolkit 开发教程:抓取交互【3.0以上版本】

获取完整课程以及答疑&#xff0c;工程文件下载&#xff1a; https://www.spatialxr.tech/ Unity XR Interaction Toolkit 系统化开发教程&#xff1a;https://www.spatialxr.tech/course/5 视频说明链接&#xff1a;抓取交互课程介绍【全球最新 Unity VR 系统化入门开发教程…

科技为翼 助残向新 高德地图无障碍导航规划突破1.5亿次

今年12月03日是第33个国际残疾人日。在当下科技发展日新月异的时代&#xff0c;如何让残障人士共享科技红利、平等地参与社会生活&#xff0c;成为当前社会关注的热点。 中国有超过8500万残障人士&#xff0c;其中超过2400万为肢残人群&#xff0c;视力障碍残疾人数超过1700万…

OGRE 3D----4. OGRE和QML共享opengl上下文

在现代图形应用开发中,OGRE(Object-Oriented Graphics Rendering Engine)和QML(Qt Modeling Language)都是非常流行的工具。OGRE提供了强大的3D渲染能力,而QML则用于构建灵活的用户界面。在某些应用场景中,我们需要在同一个应用程序中同时使用OGRE和QML,并且共享OpenGL…

YOLOv9改进,YOLOv9引入TransNeXt中的ConvolutionalGLU模块,CVPR2024,二次创新RepNCSPELAN4结构

摘要 由于残差连接中的深度退化效应,许多依赖堆叠层进行信息交换的高效视觉Transformer模型往往无法形成足够的信息混合,导致视觉感知不自然。为了解决这个问题,作者提出了一种聚合注意力(Aggregated Attention),这是一种基于仿生设计的token混合器,模拟了生物的中央凹…

坐标系变换

1 Clark变换 三相对称电压表达式为&#xff1a; 将三相电压用相量的形式表达出来&#xff0c;并用欧拉公式&#xff08;eix(cosxisinx)&#xff09;写成三角函数的形式&#xff1a; 同时&#xff0c;三相电压矢量空间合成向量可表示为&#xff1a; 三相电压合成矢量幅值为相电…

Java 上机实践10(常用实用类)

&#xff08;大家好&#xff0c;今天分享的是Java的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 Plug&#xff1a;程序实现方法一&#xff08;记事本&#xff09; 方法二&#xff08;IDEA&#xff09; 实验一&…