c++ 异常处理

异常处理:编写软件时,不仅要保证软件的正确性,同时也要有容错能力。

1.异常处理的语法:

throw表达式

当程序发现不能处理的异常时 ,可以使用throw表达式抛掷这个异常,如果有多种要抛掷的异常应该用不同的操作数来区别

try块语法:

try

复合语句

catch(异常声明)

复合语句

catch(异常声明)

复合语句

...

处理过程: 

 注意事项:

当抛出的异常与catch匹配时

  1. catch子句中声明的异常类型就是抛出异常对象的类型或引用
  2. catch子句中声明的异常类型是抛出异常对象的类型的公共基类或其引用
  3. 当抛出异常类型和catch中的声名的一仓管类型都是指针类型时,前者到后者可以隐含转换
#include<iostream>
#include<string>
using namespace std;
//处理0异常
int text(int a, int b)
{
	if (b == 0)
		//当分母为0时抛出异常
		throw a;
	return a / b;
}
int main()
{
	//try块
	try {
		cout << "3/6=" << text(3, 6) << endl;
		cout << "2/0=" << text(2, 0) << endl;
		cout << "4/5=" << text(4, 5) << endl;
	}
	//异常声明类型要与 抛出异常的类型相同
	catch (int a) {
		cout << "分母不能为0" << endl;
	}
	//当处理了异常之后后面的语句都不会处理
	cout << "结束" << endl;
	return 0;
}
catch(...)可以捕获全部异常

异常接口声明:

函数抛出异常

void fun() throw(a,b,c,d)可以抛出4种类型的异常
void fun()可以抛出所有类型的异常
void fun()throw()不抛出任何异常

当一个函数抛出了不允许抛出的异常时,unexpected函数会调用

该函数默认是调用 terminate 函数中止程序 ,用户可以自定义自己的unexpected函数

异常处理中的构造和析构:

异常抛出前会自动调用析构函数

异常被抛出后,进入try块,到异常被抛出前,这期间在栈上构造(未被析构的)的所有对象都会被自动析构,这一过程称为“解旋”

#include<iostream>
#include<string>
using namespace std;
class person
{
public:
	//初始化
	person(const string &message):message(message){}
	~person(){}
	const string &getMessage()const { return message; }
private:
	string message;
};
class son
{
public:
	//构造
	son() { cout << "1111111111111111" << endl; }
	//析构
	~son() { cout << "222222222222222" << endl; }
};
void func()throw(person)
{
	//创建一个son对象
	//调用构造函数
	son s;
	cout << "throw person in func()" << endl;
	//调用析构函数
	//抛出异常
	throw person("3333333");
}
int main()
{
	cout << "in main function" << endl;
	try {
		func();
	}
	catch (person& p)
	{
		cout << "caught an exception:" << p.getMessage() << endl;
	}
	cout << "resume the execution of main()" << endl;
	return 0;
	return 0;
}

运行结果

catch 在匹配过程中的类型转换 :

算术转换
const转换
向上转型
数组和指针的转换
用户自定的类型转换

 c++标准程序库异常处理:

基类:Exception    提供一个成员函数:what()

virtaul const char*what()const throw();

常用的一些异常类:

异常类头文件含义
bad_allocexceptionnew 动态分配空间失败
bad_casenew执行dynamic_cast失败
bad_typeidtypeinfo对某个空指针p执行统一佩戴(*p)
bad_exceptiontypeinfo

在fun()中抛出了不允许的异常调用了unexpected若unexpected又一次抛出异常了fun()的异常声明不允许的异常且fun()的异常声明表中有bed_exception则会有一个bed_exception异常在fun()的调用点被抛出

ios_base::failureios用来表示c++的输入输出流执行时的错误

underflow_error

stdexcept算术运算向下溢出
overflow_errorstdexcept算术运算向上溢出
range_errorstdexcept内部计算时发生作用域的错误
out_of_rangestdexcept表示一个参数值不在允许的范围之内
length_errorstdexcept尝试创建一个长度超过最大允许值的对象
invalid_argumentstdexcept尝试向函数传入无效参数
domain_errorstdexcept

执行一段程序的先决条件不满足

#include<iostream>
#include<string>
using namespace std;
#include<cmath>
//头文件
#include<stdexcept>
//给出三角形 三边返回面积
//异常类  invalid_argument
double area(double a, double b, double c)throw(invalid_argument)
{
	//边长都要为正数
	if (a <=0 || b <=0 || c <= 0)
	{
		throw invalid_argument("要为正数");
	}
	//两边之和大于第三边
	if (a + b <= c || a + c <= b || b + c <= a)
	{
		throw invalid_argument("两边之和要大于第三边");
	}
	double s= (a + b + c) / 2;
	return sqrt(s*(s - a)*(s - b)*(s - c));
}
int main()
{
	double a, b, c;
	cout << "请输入三个边长" << endl;
	cin >> a >> b >> c;
	try {
		double s = area(a, b, c);
		cout << "面积为:" << s;
	}
	//因为标准类都是eception的派生 所以直接创建exception类型
	catch (exception&e)
	{
		cout << "Error:" << e.what() << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值