C++异常体系

news2024/12/29 13:04:12

在这里插入图片描述

文章目录

  • 一.C++对运行时错误的处理方式
    • 函数调用链中的异常机制
  • 二.异常的使用规范
  • 三.C++异常体系
    • C++标准库中的异常体系
  • 四.关于C++异常的注意事项

一.C++对运行时错误的处理方式

  • 传统的C语言处理运行时错误采用的是assert或者错误码的方式,这种异常处理机制对错误信息的定位和描述能力都十分有限,不能满足面向对象编程的需求,C++对运行时异常的处理方式是将错误信息封装在对象中==,通过throwcatch的方式进行传递和处理
    • 关键字try:try作用域中的代码段受异常机制保护(必须和catch关键字配对)
    • 关键字catch:与try关键字配对(一个try可以匹配多个catch),用于接收try作用域代码段中特定类型的异常对象,在catch作用域中可以对异常进行处理
    • 关键字throw:代码段中用于抛出异常对象的关键字
#include <iostream>
#include <string>
using namespace std;

//用于封装错误信息的类
class Object
{
public:
	//异常对象的构造
	Object(const char * str = "")
		: _msg(str)
	{}
private:
	string _msg;
};



void function(bool judge)
{
	if (judge)
	{
		//满足某种条件,抛出临时构造的异常对象
		throw Object("程序异常");
	}
}

int main()
{
	try
	{
		//try作用域中的代码块受异常机制保护
		function(true);
	}
	catch (Object e1)//Object表示类的类型名,e1类似于函数形参(catch机制类似于函数调用)
	{
		cout << "捕获Object类型的异常" << endl;
		//处理异常
	}
	catch (...)		 //...可以捕获任意类型的异常
	{
		cout << "捕获未知异常" << endl;
		//处理异常
	}

	return 0;
}

在这里插入图片描述

  • catch关键字的参数throw抛出的对象类型必须是相匹配的,此时异常对象才能被catch接收(catch(...)可以接受任意类型的异常对象)(catch机制类似于函数调用)
  • 体系中有多个trycatch关键字组时,抛出的异常会根据对象类型匹配throw语句位置最近catch语句.
  • throw抛出的异常必须被接收,否则程序就会直接终止
  • throw抛出异常后,运行的程序将直接跳转到相应的catch作用域中,throw语句之后的代码段便无法被执行,要尤其注意这种代码跳转机制可能引发的内存泄漏问题(比如delete语句被跳过)

函数调用链中的异常机制

在这里插入图片描述

二.异常的使用规范

异常如果抛出后没有被接收,程序就会终止,因此函数的设计者应该向调用者声明函数是否能够抛出异常以及能够抛出什么类型的异常

  • void func() throw(TypeA,TypeB,TypeC,TypeD);表示函数func能够抛出TypeA,TypeB,TypeC,TypeD四种类型的异常对象
  • void func() noexcept表示函数不会抛出任何异常

三.C++异常体系

  • 为了让异常体系规范化和标准化,各异常类通常设计成一个继承体系,所有的异常类都继承自同一个父类并且让异常类重写父类的虚函数,将父类的引用作为catch的参数类型,就可以实现对所有子类异常对象的捕捉(父类和子类对象的赋值兼容),再通过多态机制就可以调用各个子类异常对象的功能接口:在这里插入图片描述
#include <iostream>
#include <string>
#include <thread>
using namespace std;

// 服务器开发中通常使用的异常继承体系
//基类Exception
class Exception
{
public:
	Exception(const string& errmsg, int id)
		:_errmsg(errmsg)
		, _id(id)
	{}
	virtual string what() const 
	{
		return _errmsg;
	}
protected:
	string _errmsg;
	int _id;
};

//子类SqlException
class SqlException : public Exception
{
public:
	SqlException(const string& errmsg, int id, const string& sql)
		:Exception(errmsg, id)
		, _sql(sql)
	{}
	//重写父类虚函数
	virtual string what() const override
	{
		string str = "SqlException:";
		str += _errmsg;
		str += "->";
		str += _sql;
		return str;
	}
private:
	const string _sql;
};

//子类CacheException
class CacheException : public Exception
{
public:
	CacheException(const string& errmsg, int id)
		:Exception(errmsg, id)
	{}
	//重写父类虚函数
	virtual string what() const override
	{
		string str = "CacheException:";
		str += _errmsg;
		return str;
	}
};

//子类HttpServerException
class HttpServerException : public Exception
{
public:
	HttpServerException(const string& errmsg, int id, const string& type)
		:Exception(errmsg, id)
		, _type(type)
	{}
	//重写父类虚函数
	virtual string what() const override
	{
		string str = "HttpServerException:";
		str += _type;
		str += ":";
		str += _errmsg;
		return str;
	}
private:
	const string _type;
};
  • 测试上面的异常体系:
//功能接口
void SQLMgr()
{
	srand(time(0));
	if (rand() % 7 == 0)
	{
		throw SqlException("权限不足", 100, "select * from name = '张三'");
	}
}
//功能接口
void CacheMgr()
{
	srand(time(0));
	if (rand() % 5 == 0)
	{
		throw CacheException("权限不足", 100);
	}
	else if (rand() % 6 == 0)
	{
		throw CacheException("数据不存在", 101);
	}
	SQLMgr();
}
//功能接口
void HttpServer()
{
	srand(time(0));
	if (rand() % 3 == 0)
	{
		throw HttpServerException("请求资源不存在", 100, "get");
	}
	else if (rand() % 4 == 0)
	{
		throw HttpServerException("权限不足", 101, "post");
	}
	CacheMgr();
}


int main()
{
	while (1)
	{
		this_thread::sleep_for(chrono::seconds(1));
		try 
		{
			HttpServer();
		}
		catch (const Exception& e) // 这里使用父类引用实现子类对象的捕捉
		{
			//多态调用
			cout << e.what() << endl;
		}
		catch (...)
		{
			//捕捉到未知异常
			cout << "Unkown Exception" << endl;
		}
	}
	return 0;
}

在这里插入图片描述

C++标准库中的异常体系

在这里插入图片描述
在这里插入图片描述

  • 一般来说,企业会开发出一套自己的异常体系来适应实际应用的需求

四.关于C++异常的注意事项

  • 异常的抛出和捕获会导致程序的执行流发生跳转,容易导致内存泄漏、死锁等异常安全问题.
  • 异常体系的设计要遵循规范:
    • 一、各个异常类型都继承自一个基类。
    • 二、函数是否抛异常,抛什么类型的异常,都要向调用者声明.
  • 尽量不要在对象的构造函数析构函数中抛出异常,避免对象的初始化和资源清理无法正常进行.
    在这里插入图片描述

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

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

相关文章

ArcGIS Pro技术应用(暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合)

GIS是利用电子计算机及其外部设备&#xff0c;采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲&#xff0c;它是在一定的地域内&#xff0c;将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来&#xff0c;达到对地理和属性信息的综合管理。GIS的…

lc137. 只出现一次的数字 II

数组排序&#xff0c;既和前不一样又和后不一样的就是唯一的一个 public static int numberOnce(int[] nums) {Arrays.sort(nums);if (nums.length > 2 && nums[0] ! nums[1]) {//避免只有一个元素的数组return nums[0];}if (nums.length > 2 && nums[nu…

994. 腐烂的橘子

题目描述&#xff1a; 主要思路&#xff1a; 宽度优先搜索&#xff0c;利用队列实现。 需要注意的是放进队列的时候就需要标记&#xff0c;而不是取出的时候再标记。 class Solution { public:int orangesRotting(vector<vector<int>>& grid) {int ngrid.siz…

解决Spring Boot 2.6及之后版本取消了循环依赖的支持的问题

目录 1、问题&#xff1a; 2、报错&#xff1a; 3、解决方案&#xff1a; 1、问题&#xff1a; 循环依赖指的是两个或者多个bean之间相互依赖,形成一个闭环。直接表现为两个service层互相调用对方。 此时会遇到以下问题&#xff1a; 2、报错&#xff1a; 当启动项目时&…

Smartbi 权限绕过漏洞复现(QVD-2023-17461)

0x01 产品简介 Smartbi大数据分析产品融合BI定义的所有阶段&#xff0c;对接各种业务数据库、数据仓库和大数据分析平台&#xff0c;进行加工处理、分析挖掘和可视化展现&#xff1b;满足所有用户的各种数据分析应用需求&#xff0c;如大数据分析、可视化分析、探索式分析、复杂…

odoo-033 比较 float 浮点数大小之精度坑

文章目录 前提原因问题 前提 产品单位精确到6位小数生产制造模块&#xff0c;重写了完成的方法&#xff0c;在点击完成的时候报错如下&#xff1a; &#xff08;解释下&#xff1a;就是很奇怪&#xff0c;明明都是必填字段&#xff0c;也都赋值了但是就是拿不到值&#xff09;…

2.若依前后端分离版第一个增删查改

1.介绍 若依提供了代码生成功能&#xff0c;单表的CRUD可以直接用若依框架提供的代码生成进行创建。 2.实现 2.1 在数据库创建业务表test_teacher 2.2 生成代码 运行系统&#xff0c;进入菜单[系统工具]-》[代码生成],点击导入按钮&#xff0c;选择需要生成代码的表进行导…

Redis储存结构

Redis怎么储存的 这个redisDb是数据库对象 里面的其他字段忽略了 然后里面有个dict列表(字典列表) 我们随便来看一个redisObject 区分一下子啊 他这个dict里面没有存redisObject的对象 也没有存dict对象 它只是存了个数据指针 你看那个redis每个底层编码 抠搜的 这块要是再保存…

信道复用技术

信道划分介质访问控制将使用介质的每个设备与来自同一通信信道上的其他设备的通信隔离开来&#xff0c;把时域和频域资源合理地分配给网络上的设备 多路复用&#xff1a;就是将多个信号组合在一条物理信道上进行传输&#xff0c;使多个计算机或终端设备共享信道资源&#xff0c…

分班查询系统学生信息在线采集方法和具体操作教程

作为教师&#xff0c;特别是临近新学年&#xff0c;我们经常需要进行学生分班工作&#xff0c;这是一项繁琐但非常重要的工作。为了提高工作效率&#xff0c;我们可以利用易查分轻松生成一个学生分班查询系统。本文将介绍如何利用易查分设计和开发这样一个系统。 我们可以选择使…

vue+element 下载压缩包和导出

export function goodsInspectionReportDwnloadZip (params) {return axios({url: "/warehouse-entry-server/v1/goodsInspectionReport/downloadZip",method: "get",params,responseType: "blob"}) } //下载handleDownloadFile() {if (!this.$r…

【LeetCode】删除并获得点数

删除并获得点数 题目描述算法分析编程代码空间优化 链接: 删除并获得点数 题目描述 算法分析 编程代码 class Solution { public:int deleteAndEarn(vector<int>& nums) {const int N 10001;int arr[N] {0};for(const auto& n : nums){arr[n]n;}vector<in…

小红书数据分析丨现实版模拟人生,这届网友热衷于“云开店”?

近期&#xff0c;小红书出现的一个神秘的热心群体&#xff0c;他们经常活跃在各种小店店主发布的求助帖评论区中&#xff0c;积极地帮助店主出谋划策&#xff0c;寻找小店经营的优化之道&#xff0c;成功帮助小店成功转亏为盈&#xff01;江湖人称一一云股东。小红书话题#爱上帮…

微信小程序启动自动检测版本更新,检测到新版本则提示更新

UpdateManager 对象&#xff0c;用来管理更新&#xff0c;可通过 wx.getUpdateManager 接口获取实例 在app.js中的示例代码 onShow() {// 获取小程序更新机制的兼容&#xff0c;由于更新的功能基础库要1.9.90以上版本才支持&#xff0c;所以此处要做低版本的兼容处理if (wx.c…

java serialport 串口助手源码 RXTX java 11还崩溃。java串口支持jdk11,jdk13,jdk14版本win10 64位系统bug修复库nrjavaserial好用

Java提供了一些API来支持串口通信。主要包括&#xff1a; javax.comm&#xff1a;Java Communications API&#xff0c;是一个用于串行通信的Java API。然而&#xff0c;这个API已经很长时间没有更新了&#xff0c;而且只支持32位的Windows系统。官网已经删。 RXTX&#xff1a;…

成功解决Linux下中文乱码问题,CentOS7设置系统字符编码

在linux中&#xff0c;可以使用以下命令查看当前系统的字符编码&#xff1a; echo $LANG 如果不是UTF-8&#xff0c;就会出现中文乱码现象! 解决办法&#xff1a;设置字符编码环境变量为utf-8 1. 打开 ~/.bashrc 或 ~/.bash_profile 文件 vi ~/.bashrc 或 vi ~/.bash_prof…

北航基于openEuler构建工业机器人操作系统,打造“开箱即用”的机器人基础软件平台

北京航空航天大学是国家“双一流”建设高校&#xff0c;以建设扎根中国大地的世界一流大学为发展目标。北京航空航天大学在机器人领域一直处于行业前沿&#xff0c;以其亮眼的成果和优秀的师资力量&#xff0c;成为国内机器人领域的重要参与者和建设者。机器人操作系统是机器人…

根证书和中间证书有什么区别?

通常即使是获取了SSL证书的人&#xff0c;也只知道他们需要SSL证书&#xff0c;而且他们必须在服务器上安装SSL证书&#xff0c;才能通过HTTPS为网站提供服务。当进一步提到中间证书、根证书时&#xff0c;大多数人都感到陌生。本文小编就将为您介绍根证书与中间证书的定义以及…

怎么采集网址、图片地址等标签属性

如果只想采集网址、图片地址等HTML标签属性的值&#xff0c;要怎么采集呢&#xff1f; 可以使用简数采集器&#xff0c;有对应的快捷提取方式&#xff0c;一键即可转换为采集网址、采集图片地址方式&#xff0c;非常方便快捷。 也可以自行设置高级提取&#xff0c;提取Html标…

vite跨域配置踩坑,postman链接后端接口正常,但是前端就是不能正常访问

问题一&#xff1a;怎么都链接不了后端地址 根据以下配置&#xff0c;发现怎么都链接不了后端地址&#xff0c;proxy对了呀。 仔细看&#xff0c;才发现host有问题 // 本地运行配置&#xff0c;及反向代理配置server: {host: 0,0,0,0,port: 80,// cors: true, // 默认启用并允…