C++知识点 -- 异常

C++知识点 – 异常

文章目录

  • C++知识点 -- 异常
  • 一、异常概念
  • 二、异常的使用
    • 1.异常的抛出和捕获
    • 2.异常的重新抛出
    • 3.异常安全
    • 4.异常规范
  • 三、自定义异常体系
  • 四、C++标准库的异常体系
  • 五、C++异常的优缺点


一、异常概念

当一个函数发现自己无法处理错误时,就可以抛出异常,让函数的直接或间接调用者处理这个错误;
throw:当函数出现问题时,会抛出一个异常,是通过throw关键字完成的;
try:try代码块中标识将被激活的特定异常;
catch:用于捕获异常;

异常捕获的基本格式:

double Div(int a, int b)
{
	if (b == 0)
	{
		throw "Division by zero condition!";
	}
	else
	{
		return a / b;
	}
}

void test()
{
	int left, right;
	cin >> left >> right;
	cout << Div(left, right) << endl;
}


int main()
{
	try 
	{
		test();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}

	return 0;
}

当b输入0时,会引发除零错误,Div函数抛出异常,main函数的catch会接收到异常;
在这里插入图片描述

二、异常的使用

1.异常的抛出和捕获

(1)异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码;
(2)被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个;

在这里插入图片描述

(3)抛出异常对象后,会生成一个异常对象的拷贝,因为抛出异常的对象可能是一个临时对象,所以会生成一个拷贝,这个拷贝的临时对象在被catch后会销毁;(类似于函数的传值返回)
(4)catch(…)可以捕获任意类型的异常,但是不知道异常错误是什么;

int main()
{
	try 
	{
		test();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}
	catch (const int errid)//异常抛出与捕获的类型一定要匹配,如果catch没有匹配的类型,程序会直接终止
	{
		cout << errid << endl;
	}
	catch (...)//捕获任意类型的异常,防止出现未捕获异常时 ,程序终止
	{
		cout << "未知异常" << endl;
	}

	return 0;
}

(5)实际中抛出和捕获的匹配原则有个例外,可以抛出派生类对象,用基类捕获;

2.异常的重新抛出

double Div(int a, int b)
{
	if (b == 0)
	{
		throw "Division by zero condition!";
	}
	else
	{
		return a / b;
	}
}

void test()
{
	int* array1 = new int[10];
	int* array2 = new int[5];

	int left, right;
	cin >> left >> right;
	try 
	{
		cout << Div(left, right) << endl;
	}
	catch (...)
	{
		throw;//捕获什么抛什么
	}
	cout << "delete[]" << array1 << endl;
	delete[] array1;
	cout << "delete[]" << array1 << endl;
	delete[] array2;
}


int main()
{
	try 
	{
		test();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}
	return 0;
}

这里可以看到如果发生除0错误抛出异常,另外下面的array没有得到释放。
所以这里捕获异常后并不处理异常,异常还是交给外面处理,这里捕获了再重新抛出去。

可以在异常重新抛出前释放空间:

void test()
{
	int* array1 = new int[10];
	int* array2 = new int[5];

	int left, right;
	cin >> left >> right;
	try 
	{
		cout << Div(left, right) << endl;
	}
	catch (...)
	{
		cout << "delete[]" << array1 << endl;
		delete[] array1;
		cout << "delete[]" << array1 << endl;
		delete[] array2;

		throw;//捕获什么抛什么
	}
}

3.异常安全

(1)最好不要在构造函数中抛异常,否则可能会导致对象不完整或没有完全初始化;
(2)最好不要在析构函数中抛出异常,否则可能导致资源泄露;
(3)c++中经常会在new和delete中间怕抛出异常,导致资源泄露,应使用RAII来解决该问题;

4.异常规范

(1)异常规格说明目的为了让函数使用者知道该函数会抛出那些类型的异常,可以在函数名后面接throw(类型),列出这个函数可能抛出的所有有异常类型;

void fun() throw(int, char*);

(2)函数后面接throw()或noexcept,表示函数不抛异常;

void fun() throw();
void fun() noexcept;//c++11中新增的noexcept表示函数不会抛异常

(3)若无异常接口声明,则此函数可以抛出任意类型的异常;

三、自定义异常体系

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

	virtual string what() const
	{
		return _errmsg;
	}

	int getid() const
	{
		return _id;
	}

protected:
	string _errmsg;   // 错误信息
	int _id;          // 错误码
};

class SqlException : public Exception
{
public:
	SqlException(const string& errmsg, int id, const string& sql)
		:Exception(errmsg, id)
		, _sql(sql)
	{}

	virtual string what() const
	{
		string str = "SqlException:";
		str += _errmsg;
		str += "->";
		str += _sql;

		return str;
	}
protected:
	const string _sql;
};

class CacheException : public Exception
{
public:
	CacheException(const string& errmsg, int id)
		:Exception(errmsg, id)
	{}

	virtual string what() const
	{
		string str = "CacheException:";
		str += _errmsg;
		return str;
	}

protected:
	// stack<string> _stPath;
};

class HttpServerException : public Exception
{
public:
	HttpServerException(const string& errmsg, int id, const string& type)
		:Exception(errmsg, id)
		, _type(type)
	{}

	virtual string what() const
	{
		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 = '张三'");
	}

	cout << "本次请求成功" << endl;
}

void CacheMgr()
{
	srand(time(0));
	if (rand() % 5 == 0)
	{
		throw CacheException("权限不足", 200);
	}
	else if (rand() % 6 == 0)
	{
		throw CacheException("数据不存在", 201);
	}

	SQLMgr();
}

void SeedMsg(const string& s)
{
	// 要求出现网络错误重试三次
	srand(time(0));
	if (rand() % 3 == 0)
	{
		throw HttpServerException("网络错误", 100, "get");
	}
	else if (rand() % 4 == 0)
	{
		throw HttpServerException("权限不足", 101, "post");
	}

	cout << "发送成功:" << s << endl;
}

void HttpServer()
{
	// 要求出现网络错误,重试3次
	string str = "今晚一起看电影怎么样?";
	//cin >> str;
	int n = 3;
	while (n--)
	{
		try
		{
			SeedMsg(str);

			// 没有发生异常
			break;
		}
		catch (const Exception& e)
		{
			// 网络错误 且  重试3次内
			if (e.getid() == 100 && n > 0)
			{
				continue;
			}
			else
			{
				throw e; // 重新抛出
			}
		}
	}
}
//在这里接收了异常后,如果不重新抛出,外面就接受不到其他异常了
//如果SeedMsg没有抛异常就break
//如果SeedMsg抛异常就会走到catch,如果是网络错误,continue重试3次,3次后还是错误,就重新抛出异常,外面会接收到网络异常
//如果SeedMsg抛出其他异常,直接抛出,让外面接收

int main()
{
	while (1)
	{
		//this_thread::sleep_for(chrono::seconds(1));
		Sleep(1000);

		try
		{
			HttpServer();
		}
		catch (const Exception& e) // 这里捕获父类对象就可以
		{
			// 多态
			cout << e.what() << endl;
			// 记录日志
		}
		catch (...)
		{
			cout << "Unkown Exception" << endl;
		}
	}

	return 0;
}

所有的子类异常类都继承于父类异常类,这样在捕获时,统一用父类对象捕获,能够触发多态;

四、C++标准库的异常体系

在这里插入图片描述

五、C++异常的优缺点

优点
(1)相比错误码能狗更加清晰地展现出错误信息,能够更好的定位bug;
(2)传统错误码在函数调用链中,深层函数返回了错误,那么我们得层层返回,最外层才能拿到错误,如果是异常体系,我们可以自由设置在哪层接受异常;
(3)很多第三方库都包含异常,所以我么也要使用异常;
(4)部分函数使用异常更好处理,比如构造函数没有返回值,不方便使用错误码处理;

缺点
(1)会导致程序的执行流乱跳;
(2)异常会有一些性能的消耗;
(3)C++没有垃圾回收机制,资源需要自己清理,一般使用RAII;
(4)C++标准库异常体系定义的不好;
(5)尽量规范使用异常,否则后果不堪设想;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

14-3-进程间通信-消息队列

前面提到的管道pipe和fifo是半双工的&#xff0c;在某些场景不能发挥作用&#xff1b; 接下来描述的是消息队列&#xff08;一种全双工的通信方式&#xff09;&#xff1b; 比如消息队列可以实现两个进程互发消息&#xff08;不像管道&#xff0c;只能1个进程发消息&#xff…

kali: kali工具-Ettercap

kali工具-Ettercap ettercap工具&#xff1a; 用来进行arp欺骗&#xff0c;可以进行ARP poisoning&#xff08;arp投毒&#xff09;&#xff0c;除此之外还可以其他功能&#xff1a; ettercap工具的arp投毒可以截取web服务器、FTP服务器账号密码等信息&#xff0c;简略后打印出…

前端学习之使用JavaScript

前情回顾&#xff1a;网页布局 JavaScript 简介 avaScript诞生于1995年&#xff0c;它的出现主要是用于处理网页中的前端验证。所谓的前端验证&#xff0c;就是指检查用户输入的内容是否符合一定的规则。比如&#xff1a;用户名的长度&#xff0c;密码的长度&#xff0c;邮箱的…

SQL中去除重复数据的几种方法,我一次性都告你​

使用SQL对数据进行提取和分析时&#xff0c;我们经常会遇到数据重复的场景&#xff0c;需要我们对数据进行去重后分析。 以某电商公司的销售报表为例&#xff0c;常见的去重方法我们用到distinct 或者group by 语句&#xff0c; 今天介绍一种新的方法&#xff0c;利用窗口函数…

Github 的使用

3. Github 在版本控制系统中&#xff0c;大约90%的操作都是在本地仓库中进行的&#xff1a;暂存&#xff0c;提交&#xff0c;查看状态或者历史记录等等。除此之外&#xff0c;如果仅仅只有你一个人在这个项目里工作&#xff0c;你永远没有机会需要设置一个远程仓库。只有当你…

2001-2021年全国30省就业人数数据

2001-2021年全国30省就业人数数据/各省就业人数数据 1、时间&#xff1a;2001-2021年 2、范围&#xff1a;包括30个省市不含西藏 3、指标&#xff1a;就业人数 4、来源&#xff1a;各省NJ、社会统计NJ 5、缺失情况说明&#xff1a;无缺失 6、指标说明&#xff1a; 就业人…

实在智能出席第六届数字中国建设峰会,入围2022年信息技术应用创新优秀解决方案榜单

最美榕城四月天&#xff0c;山海之间尽显数字澎湃。这一周来&#xff0c;实在智能来到了“有福之州”&#xff0c;为数字中国建设增添实在色彩。 4月25日&#xff0c;实在华夏行抵达福州站&#xff0c;与众多生态合作伙伴携手共话数字发展新未来&#xff1b; 4月26日&#xff…

分布式事务 --- Seata事务模式、高可用

一、事务模式 1.1、XA模式 XA 规范 是 X/Open 组织定义的分布式事务处理&#xff08;DTP&#xff0c;Distributed Transaction Processing&#xff09;标准&#xff0c;XA 规范 描述了全局的TM与局部的RM之间的接口&#xff0c;几乎所有主流的数据库都对 XA 规范 提供了支持。…

ContextCapture Master 倾斜摄影测量实景三维建模技术应用

查看原文>>>ContextCapture Master 倾斜摄影测量实景三维建模技术应用 目录 第一部分、倾斜摄影测量原理及应用领域 第二部分、倾斜摄影测量数据采集方法 第三部分、CC支持数据类型及导入数据方法 第四部分、CC空三计算参数设置及数据处理方法 第五部分、CC控制…

电气电工相关专业知识及名词解释

一、电流电压 火线、零线、地线&#xff1a;火线和零线的区别就是&#xff1a;火线带电&#xff0c;零线不带电。火线是传电流的&#xff0c;而零线是回流的。 红色是火线&#xff0c;零线一般是绿色的&#xff0c;通常可用电笔来测。电笔一头亮了是火线&#xff0c;不亮的则…

Python使用CV2库捕获、播放和保存摄像头视频

Python使用CV2库捕获、播放和保存摄像头视频 特别提示&#xff1a;CV2指的是OpenCV2&#xff08;Open Source Computer Vision Library&#xff09;&#xff0c;安装的时候是 opencv_python&#xff0c;但在导入的时候采用 import cv2。 若想使用cv2库必须先安装&#xff0c;P…

InnoDB 引擎 底层逻辑

目录 0 课程视频 1 逻辑存储结构 1.1 结构图 1.2 表空间 -> 记录 索引 存储记录 等数据 1.2.1 储存在 cd/var/lib/mysql -> ll -> 目录 mysql.ibd 1.3 段 -> 索引 存储记录 具体存储 1.3.1 数据段 b树 叶子节点 1.3.2 索引段 b树的 非叶子节点 1.3.3 回滚段…

ChatGPT来了不用慌,广告人还有这个神器在手

#ChatGPT能取代广告人吗&#xff0c;#ChatGPT会抢走你的工作吗&#xff1f;#ChatGPT火了&#xff0c;会让营销人失业吗&#xff1f;自ChatGPT爆火以来&#xff0c;各种专业or非专业文章不停给广告人强加焦虑&#xff0c;但工具出现的意义&#xff0c;更多在于提效而非替代&…

【技术分享】防止根据IP查域名,防止源站IP泄露

有的人设置了禁止 IP 访问网站&#xff0c;但是别人用 https://ip 的形式&#xff0c;会跳到你服务器所绑定的一个域名网站上 直接通过 https://IP, 访问网站&#xff0c;会出现“您的连接不是私密连接”&#xff0c;然后点高级&#xff0c;会出现“继续前往 IP”&#xff0c;…

简单分享微信小程序上的招聘链接怎么做

招聘小程序的主要用户就是企业招聘端和找工作人员的用户端,下面从这两个端来对招聘小程序开发的功能进行介绍。 企业端功能 1、岗位发布:企业根据自身岗位需求,在招聘app上发布招聘岗位及所需技能。 2.简历筛选:根据求职者提交的简历选择合适的简历,并对公开发布的简历进行筛…

【五一创作】【Simulink】采用延时补偿的三相并网逆变器FCS-MPC

&#x1f449; 【Simulink】基于FCS-MPC的三相并网逆变器控制 上一篇博客介绍了FCS-MPC的基本操作&#xff0c;并且以三相并网逆变器为控制对象进行了Simulink仿真。 但实际仿真中没有考虑补偿延时。本篇博客将讨论为什么要考虑延时并进行补偿&#xff0c;最后对此仿真验证。 …

【Java数据结构】顺序表、队列、栈、链表、哈希表

顺序表 定义 存放数据使用数组但是可以编写一些额外的操作来强化为线性表&#xff0c;底层依然采用顺序存储实现的线性表&#xff0c;称为顺序表 代码实现 创建类型 先定义一个新的类型 public class ArrayList<E> {int capacity 10; //顺序表的最大容量int size …

【Java笔试强训 6】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;不要二 …

基于微信小程序的垃圾分类系统的研究与实现(附源码和教程)

1. 简介 本文介绍的事基于微信小程序的垃圾分类系统&#xff0c;主要实现的功能有登录、注册、垃圾分类查询、垃圾预约回收、垃圾分类功能。 2.系统设计与实现 本章节是论文的重点&#xff0c;基于上一章介绍的总体设计框架的搭建&#xff0c;详细对小程序的页面布局、流程设…

Photoshop如何使用选区之实例演示?

文章目录 0.引言1.利用快速选择工具抠图2.制作网店产品优惠券3.利用选区改变眼睛颜色4.抠取复杂的花束5.制作丁达尔光照效果6.利用选区调整图像局部颜色 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对PS进行了学习&#xff0c;本文通过《Photoshop2021入门教程》及…