异常——浅析

异常

本人不才,对于异常只能做基本的介绍,无法给出自己的体会以及无法指明易错点

C异常

c语言处理异常的方式有
assert——直接中断程序
返回错误码——需要查找错误码表确定错误
这两种操作都不是很好,如果一个大型程序,为了找到一个错误,加载都需要半天,一遍又一遍的运行调试,是不是就很耗时间
于是c++就有了异常处理机制


C++异常

c++异常做到了程序自己检查异常,自己抛出异常,统一进行捕获,最重要的就是程序不会挂掉

通常有三部:
try——确定可能发异常的代码片段
throw——抛出异常
catch——捕获异常


double div()
{
	int a, b;
	cin >> a >> b;
	if (a == 0 && b == 0) throw(1);
	else if (b == 0) throw("div发生除0错误");
	else if (a == 3 && b == 3) throw(1.1);
	else if (a == 4 && b == 4) throw(1, 'c');

	return (double)a / b;
}
void test()
{
	while (1)
	{
		try
		{
			cout << div() << endl;
		}
		catch (const char* s)
		{
			puts(s);
		}
		catch (int a)
		{
			printf("%d\n", a);
		}
		catch (char c)
		{
			printf("%d\n", c);
		}
		catch (...)
		{
			puts("未知异常");
		}
	}

}

一个throw只能抛出一个错误,一个catch也只能捕捉一个错误
else if (a == 4 && b == 4) throw(1, 'c');
上面代码中,throw并不是抛出两个,而是采用逗号表达式的形式进行计算,最终抛出的是char类型

异常的匹配规则
1.抛出什么类型,就是去找匹配的类型:int->int,char*->char*,char->char

这里的匹配是很严格的,int不会去找char,char也不会去找int(他们都可以转换成整型,他们都不相互串门,确实很严格)
在这里插入图片描述
在这里插入图片描述

2.抛出错误,往前找,找到最近的位置进行捕捉
在mian函数中添加try-catch,验证抛int异常能不能再mian中捕捉到

double div()
{
	int a, b;
	cin >> a >> b;
	if (a == 0 && b == 0) throw(1);
	else if (b == 0) throw("div发生除0错误");
	else if (a == 3 && b == 3) throw(1.1);
	else if (a == 4 && b == 4) throw(1, 'c');

	return (double)a / b;
}
void test()
{
	while (1)
	{
		try
		{
			cout << div() << endl;
		}
		catch (int a)
		{
			printf("%d\n", a);
		}
		//catch (char c)
		//{
		//	printf("%d\n", c);
		//}
		catch (...)
		{
			puts("未知异常");
		}
	}

}
int main()
{
	try 
	{
		test();
	}
	catch (int a)
	{
		puts("main");
	}
	return 0;
}

在这里插入图片描述
3.对于抛出错误,直接跳到捕捉位置,中间产生的函数栈帧会逐层进行回收,但是throw后的代码不会执行

double div()
{
	int a, b;
	cin >> a >> b;
	if (a == 0 && b == 0) throw(1);
	else if (b == 0) throw("div发生除0错误");
	else if (a == 3 && b == 3) throw(1.1);
	else if (a == 4 && b == 4) throw(1, 'c');
	puts("---");

	return (double)a / b;
}

在这里插入图片描述
没有执行div函数中的puts

异常安全

1.不要再构造函数内部抛异常
2.不要在析构函数内抛异常

异常规范

使用 noexcept关键字表示这个函数不会抛出异常,如果抛出异常会进行报警——这中方式比较强硬
在这里插入图片描述
也可以使用throw(...)再括号中可以添加任意多个类型,添加在某个函数之后,表示这个函数可以抛出的错误类型;不写表示不会抛出,但是如果抛出了也不会报错
在这里插入图片描述

标准异常库

再引入execption库之后就可以使用库中的类了
只需要写一句,就可以捕捉类中所能抛出的所有异常,并使用what函数进行打印

	throw invalid_argument("b=0");
	
	catch (const exception& e)
	{
		cout << e.what() << endl;
	}

在这里插入图片描述
重中之重
1.异常规范有两点:
一、抛出异常类型都继承自一个基类
二、函数是否抛异常、抛什么异常,都使用 func() throw();的方式规范化。
2.异常可能造成内存泄漏,人们为了解决这个问题就产生了——智能指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值