5.6 try语句块和异常处理


异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围。典型的异常包括失去数据库连接以及遇到意外输入等。

当程序的某部分检测到一个它无法处理的问题时,需要用到异常处理。此时,检测出问题的部分应该发出某种信号以表明程序遇到了故障,无法继续下去了,而且信号的发出方无须知道故障将在何处得到解决。一旦发出异常信号,检测出问题的部分也就完成了任务。

如果程序中含有可能引发异常的代码,那么通常也会有专门的代码处理问题。例如,如果程序的问题是输入无效,则异常处理部分可能会要求用户重新输入正确的数据;如果丢失了数据库连接,会发出报警信息。

异常处理机制为程序中异常检测异常处理这两部分的协作提供支持。在C++语言中,异常处理包括:

  1. throw表达式,异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们说throw引发了异常。
  2. try语句块,异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句结束。try 语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句“处理”异常,所以它们也被称作异常处理代码。
  3. 一套异常类,用于在throw表达式和相关的catch子句之间传递异常的具体信息。

throw表达式(异常检测)

程序的异常检测部分使用throw表达式引发一个异常。

语法:

throw 错误的类型(例如:runtime_error)(构造函数);

举个例子:

#include<iostream>
#include<string>
using namespace std;

int main()
{
	int item1, item2;
	cin >> item1 >> item2;
	if (item1==item2)
	{
		throw runtime_error("Datas aren't same!");
	}
	else
	{
		cout << item1 + item2;
	}
	return 0;
}

在这段代码中,如果两个item一样就抛出一个异常,该异常是类型runtime_error 的对象。抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码

类型runtime_ error 是标准库异常类型的一种,定义在stdexcept头文件中。我们必须初始化runtime_ error 的对象,方式是给它提供一个string对象或者一个C风格的字符串,这个字符串中有一些关于异常的辅助信息。

try语句块(异常处理)

try 语句的基本格式:

try{
program-statement
}catch(exception-declaration){
handler-statements
}catch(exception-declaration){
handler-statements
}
······

try语句块的一开始是关键字try,随后紧跟着一个块,这个块就像大多数时候那样是花括号括起来的语句序列。

跟在try 块之后的是一个或多个catch 子句。catch子句包括三部分:关键字catch、括号内一个(可能未命名的)对象的声明(称作异常声明,exception declaration)以及一个块。当选中了某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。

try语句块中的program-statements 组成程序的正常逻辑,像其他任何块一样,program-statements可以有包括声明在内的任意C++语句。一如往常,try语句块内声明的变量在块外部无法访问,特别是在catch子句内也无法访问。

编写处理代码

#include<iostream>
#include<string>
using namespace std;

int main()
{
	int item1, item2;
	cin >> item1 >> item2;
	if (item1==item2)
	{
		try
		{
			throw runtime_error("Data must refer to same ISBN");//1
		}
		catch (runtime_error err)//2
		{
			cout << err.what();//3
		}
	}
	else
	{
		cout << item1 + item2;
	}
	return 0;
}

这里有三个值得注意的点:

  1. throw runtime_error(“Data must refer to same ISBN”);这一句是抛出异常是runtime_error当中的一个异常,并对其进行初始化。
  2. runtime_error err 将异常接受并且进行初始化给自己定义的一个变量。
  3. 异常处理对象.what()输出的是初始化时传入内部的值。

函数在寻找处理代码的过程中退出

在复杂系统中,程序在遇到抛出异常的代码前,其执行路径可能已经经过了多个try语句块。例如,一个try语句块可能调用了包含另一个try语句块的函数,新的try语句块可能调用了包含又一个try语句块的新函数,以此类推。

寻找处理代码的过程与函数调用链刚好相反。当异常被抛出时,首先搜索抛出该异常的函数。如果没找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。如果还是没有找到匹配的catch 子句,这个新的函数也被终止,继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直到找到适当类型的catch子句为止。如果最终还是没能找到任何匹配的catch子句,程序转到名为terminate 的标准库函数。该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。对于那些没有任何try语句块定义的异常,也按照类似的方式处理:毕竟,没有try语句块也就意味着没有匹配的catch子句。如果一段程序没有 try语句块且发生了异常,系统会调用terminate函数并终止当前程序的执行。(这一段好好进行理解

但是实际上这个函数用不到,我们只要未进行定义的异常,都会自动进行退出。

例子:

#include<iostream>
#include<string>
using namespace std;

int main()
{
	int item1, item2;
	cin >> item1 >> item2;
	if (item1==item2)
	{
		try
		{
			throw runtime_error("Data must refer to same ISBN");
		}
		catch (runtime_error err)
		{
			cout << err.what();
			terminate();
		}
	}
	else
	{
		cout << item1 + item2;
	}
	return 0;
}

输出结果:
在这里插入图片描述

标准异常

C++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类也可以在用户编写的程序中使用,它们分别定义在4个头文件中:

  1. exception头文件定义了最通用的异常类exception。它只报告异常的发生,不提供任何额外信息。
  2. stdexcept头文件定义了几种常用的异常类,详细信息如下表。
错误描述
exception最常见的问题
runtime_error只有运行的时候才能检测出的问题
range_error运行时错误:生成的结果超过了有意义的值域范围
overflow_error运行时错误:计算上溢
underflow_error运行时错误:计算下溢
logic_error程序逻辑错误
domain_error逻辑错误:参数对应的结果值不存在
invalid_argument逻辑错误,无效参数
length_error逻辑错误:试图创建一个超出该类型最大长度的对象
out_of_range逻辑错误:使用一个超出有效范围的值

但如果要自己写try的话我们都写runtime_error即可。剩下的自己理解一下,后面自己敲代码的时候出现这些错误,知道是什么错误即可。

  1. new头文件定义了bad alloc异常类型,这种类型将在之后进行介绍。
  2. type_ info头文件定义了bad_ cast异常类型,这种类型将在之后进行介绍。

what函数返回的字符串内容和异常处理对象的类型有关。如果异常处理类型有一个字符串初始值,则what返回该字符串。对于其他无初始值的异常类型来说,what返回的内容由编译器决定。

最后给一段代码大家理解一下:

#include<iostream>
#include<string>
using namespace std;

int main()
{
	int item1, item2;
	cin >> item1 >> item2;
	if (item2==0)
	{
		try
		{
			throw runtime_error("除数不能为0");
		}
		catch (runtime_error err)
		{
			cout << err.what()<<endl<< "try again!"<<endl;
			cin >> item1 >> item2;
		}
	}
	cout << item1 / item2;
	return 0;
}

输出结果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ Primer中文版(第5版)[203M]分3个压缩包 本书是久负盛名的C++经典教程,其内容是C++大师Stanley B. Lippman丰富的实践经验和C++标准委员会原负责人Josée Lajoie对C++标准深入理解的完美结合,已经帮助全球无数程序员学会了C++。 对C++基本概念和技术全面而且权威的阐述,对现代C++编程风格的强调,使本书成为C++初学者的最佳指南;对于中高级程序员,本书也是不可或缺的参考书。 目录 第1章 开始 1   1.1 编写一个简单的C++程序 2   1.1.1 编译、运行程序 3   1.2 初识输入输出 5   1.3 注释简介 8   1.4 控制流 10   1.4.1 while语句 10   1.4.2 for语句 11   1.4.3 读取数量不定的输入数据 13   1.4.4 if语句 15   1.5 类简介 17   1.5.1 Sales_item类 17   1.5.2 初识成员函数 20   1.6 书店程序 21   小结 23   术语表 23   第Ⅰ部分 C++基础 27   第2章 变量和基本类型 29   2.1 基本内置类型 30   2.1.1 算术类型 30   2.1.2 类型转换 32   2.1.3 字面值常量 35   2.2 变量 38   2.2.1 变量定义 38   2.2.2 变量声明和定义的关系 41   2.2.3 标识符 42   2.2.4 名字的作用域 43   2.3 复合类型 45   2.3.1 引用 45   2.3.2 指针 47   2.3.3 理解复合类型的声明 51   2.4 const限定符 53   2.4.1 const的引用 54   2.4.2 指针和const 56   2.4.3 顶层const 57   2.4.4 constexpr和常量表达式 58   2.5 处理类型 60   2.5.1 类型别名 60   2.5.2 auto类型说明符 61   2.5.3 decltype类型指示符 62   2.6 自定义数据结构 64   2.6.1 定义Sales_data类型 64   2.6.2 使用Sales_data类 66   2.6.3 编写自己的头文件 67   小结 69   术语表 69   第3章 字符串、向量和数组 73   3.1 命名空间的using声明 74   3.2 标准库类型string 75   3.2.1 定义和初始化string对象 76   3.2.2 string对象上的操作 77   3.2.3 处理string对象中的字符 81   3.3 标准库类型vector 86   3.3.1 定义和初始化vector对象 87   3.3.2 向vector对象中添加元素 90   3.3.3 其他vector操作 91   3.4 迭代器介绍 95   3.4.1 使用迭代器 95   3.4.2 迭代器运算 99   3.5 数组 101   3.5.1 定义和初始化内置数组 101   3.5.2 访问数组元素 103   3.5.3 指针和数组 105   3.5.4 C风格字符串 109   3.5.5 与旧代码的接口 111   3.6 多维数组 112   小结 117   术语表 117   第4章 表达式 119   4.1 基础 120   4.1.1 基本概念 120   4.1.2 优先级与结合律 121   4.1.3 求值顺序 123   4.2 算术运算符 124   4.3 逻辑和关系运算符 126   4.4 赋值运算符 129   4.5 递增和递减运算符 131   4.6 成员访问运算符 133   4.7 条件运算符 134   4.8 位运算符 135   4.9 sizeof运算符 139   4.10 逗号运算符 140   4.11 类型转换 141   4.11.1 算术转换 142   4.11.2 其他隐式类型转换 143   4.11.3 显式转换 144   4.12 运算符优先级表 147   小结 149   术语表 149   第5章 语句 153   5.1 简单语句 154   5.2 语句作用域 155   5.3 条件语句 156   5.3.1 if语句 156   5.3.2 switch语句 159   5.4 迭代语句 165   5.4.1 while语句 165   5.4.2 传统的for语句 166   5.4.3 范围for语句 168   5.4.4 do while语句 169   5.5 跳转语句 170   5.5.1 break

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值