当前课程知识点:C++语言程序设计进阶 >  第十二章 异常处理 >  异常处理的思想与程序实现 >  异常处理的思想与程序实现

返回《C++语言程序设计进阶》慕课在线视频课程列表

异常处理的思想与程序实现在线视频

异常处理的思想与程序实现

异常处理的思想与程序实现

异常处理的基本思想

12-1.png

异常处理的语法

12-2.png

例12-1处理除零异常

//12_1.cpp
#include <iostream>
using namespace std;
int divide(int x, int y) {
    if (y == 0)
        throw x;
    return x / y;
}
int main() {
    try {
        cout << "5 / 2 = " << divide(5, 2) << endl;
        cout << "8 / 0 = " << divide(8, 0) << endl;
        cout << "7 / 1 = " << divide(7, 1) << endl;
    } catch (int e) {
        cout << e << " is divided by zero!" << endl;
    }
    cout << "That is ok." << endl;
    return 0;
}

异常接口声明



下一节:异常处理中的构造与析构

返回《C++语言程序设计进阶》慕课在线视频列表

异常处理的思想与程序实现课程教案、知识点、字幕

大家好

欢迎继续学习C++语言程序设计

这一节我们来学习

异常处理的思想和程序实现

首先呢

我们通过一个图

让大家来了解一下

异常处理的基本思想

从这张图我们可以看到

在引发异常的模块中呢

有可能我们是不处理异常的

也就是说

某一个函数h

在它运行期间

可能发生了环境

或者用户使用的故障

那么这个时候呢

导致计算不能够继续下去了

但是函数h

它自己可以并不去处理这个异常

谁调用了它呢

它就将这个异常

抛送给它的调用者

比如说函数g

可能是函数h的调用者

函数g接收到抛出的异常以后呢

它可以选择处理这个异常

或者不处理

继续向它的调用者再次抛出

那么异常有可能

就沿着调用栈一级一级向上抛出

直到某一级函数

它的分工就是捕获

并且处理这些异常

那么它就把这些异常问题

在这里处理

这样的话呢

我们就看到

实际上这个异常的抛出方向

和函数的调用方向

正好是反过来的

所以异常的抛出

都是向它的上级调用者去抛出

那么这就是异常处理的基本思想

当程序运行过程中

发现用户使用行为不当

或者环境因素造成

计算无法继续的时候

那么C++

给我们提供的异常处理机制

可以让程序具有容错功能

这个容错功能

又不用干扰程序执行的主逻辑

不是说在发生异常的当地

总是立即处理异常

而是可以选择你处理也行

不处理

直接向上抛给调用者也行

那么调用者同样可以继续上抛

这样我们就可以

将不同的模块进行分工

让它们有分工 有合作

有的模块专注于执行

主要的计算逻辑

而有的模块呢

专门用来做各种各样的容错处理

现在我们来看一下

异常处理的语法

在程序段中

如果遇到有异常呢

可以通过throw

创建一个异常对象

并且抛出

那么抛出以后

怎么能够使得

该处理异常的程序段

能够得到这个异常信息呢

我们就需要一个抛出

和捕获配合的这样一个机制

也就是说

我们需要

将可能抛出异常的程序段

放在这个try块里面

那么通过正常的顺序

执行到try语句以后

会执行try块里面的内容

我们叫保护段

如果在保护段执行期间

没有引发异常

因为异常不是说一定要出现的

异常是非常偶然的情况

它会偶然出现

那么大多数情况下

我们执行

这个try保护段里面的内容

都不会引起异常

那么这个时候

跟在try块后面的catch子句

就不会被执行

程序会从try块以后的

最后一个catch之后的语句

继续执行

catch子句呢

会按照它在try块后

出现的顺序依次被检查

当try块里面有异常抛出的时候

那么try块后面

属于列出了多个catch块

它就从前往后依次检查

抛出的异常对象

跟哪个catch子句里面的

异常声明类型匹配了

那么就进入哪个catch子句

里面的catch块

这个catch块里面的内容呢

往往是进行异常处理

如果说所有catch中的异常声明

都没有匹配上

也就是匹配的处理器没有找到

那么库函数terminate

就会被自动调用

那么它默认的功能

就是调用abort终止这个程序

下面我们来看一个例子

在这个例子中呢

通过异常处理机制

来处理除0异常

这里我们将这个除法运算

交给函数divide来完成

传给它两个参数x y

希望它去计算x除以y

首先它就要判断

这个除数是否是0

如果除数是0

就不能做这个除法

直接将第一个参数x

作为异常对象抛出

当然了抛出异常对象

可以是一个我们为了

这种异常情况

构造的一个包含很多信息的对象

也可以

就是一个基本数据类型的变量

现在就将x这个被除数本身

作为异常对象抛出了

你抛出什么类型的数据

作为异常对象都可以

只要抛出和接收约定好就行

如果除数不为0的话

就计算x除以y

好 现在看主函数中

既然这个divide函数

是有可能抛出异常的

所以我们将三次对divide的调用

都放在try块里面

后面这个catch块就来捕获异常

注意

这里捕获的是一个int类型的

异常对象

这跟我们这个divide

抛出的异常类型

正好是约定好的了

它要抛出

也是抛出一个int作为异常对象

那么这儿catch当然就是匹配

接收一个int作为异常对象

第一次调用它的时候

给的参数是5和2

计算5除以2是没有问题的

大家看这个结果反馈回来了

第二次呢

调用的时候给的参数是8和0

也就是这意思是要计算8除以0

当然这个divide函数一判断

除数为0

它就不会做这个除法

就直接将第一个参数8

作为异常对象抛出了

所以

后面这个除法就没有计算

抛出了以后

这个try块后面的运算

7除以1也就不会再执行了

try块后面所有的东西都停止

不执行了

直接就到catch子句这儿来

去捕获

正好捕获的也是一个整数

于是就把这个异常对象捕获到了

然后就将这个信息输出

e被0除了

我们看到输出的是8

被0除

然后That is ok

程序就此结束

所以我们看到

这是一个典型的

也就是特别简单的

遇到了异常

不再就地处理

直接抛出给它的调用者

它的调用者呢

将有可能抛出异常的代码

都放在try块里面

后面用catch去捕获这个异常

这是一个典型的异常处理机制

如果一个函数

它知道自己有可能抛出

哪些类型的异常

最好就在编写函数的时候

声明一下

我这个函数是预期有可能抛出

什么什么类型异常的

这样显示声明以后

程序的可读性就比较好

这样这个函数的调用者

就能够知道

它调用的函数

是有可能抛出哪些异常的

这样在调用者函数中呢

就比较方便

为处理这些异常做好准备

我们看

这就是异常接口声明机制

所谓异常接口声明

我们看它的语法就是这样的

在函数声明的时候

加一个throw

throw后面这一对括号里面

就列出这个函数

它运行时有可能抛出的异常类型

打算抛出多少个类型的异常

就列多少个类型在这儿

那么如果一个函数

它没有进行异常接口声明

那恰恰说明这个函数

它有可能抛出任何类型的异常

那它都可能

抛出任何类型的异常了

它的调用者就很难专门针对性地

为某种异常去做好准备了

所以呢

建议大家写函数的时候

如果它有可能抛出异常

你一定列出它打算抛出什么异常

如果一个函数

肯定不会抛出异常的

我们也可以去

写一个throw

后面一对空括号

那就表示这个函数

不会抛出任何异常

C++语言程序设计进阶课程列表:

第七章 继承与派生

-导学

--导学

-继承的基本概念和语法

--继承的基本概念和语法

-第七章 继承与派生--继承的基本概念和语法习题

-继承方式

--继承方式简介及公有继承

--私有继承和保护继承

-第七章 继承与派生--继承方式

-基类与派生类类型转换

--基类与派生类类型转换

-第七章 继承与派生--基类与派生类类型转换

-派生类的构造和析构

--派生类的构造函数

--派生类的构造函数举例

--派生类的复制构造函数

--派生类的析构函数

--第七章 继承与派生--派生类的构造和析构

-派生类成员的标识与访问

--访问从基类继承的成员

--虚基类

-第七章 继承与派生--派生类成员的标识与访问

-小结

--小结

-综合实例

--第七章综合实例

-实验七

--实验七

-第七章讲义

第八章 多态性

-导学

--导学

-第八章 多态性--导学

-运算符重载

--运算符重载的规则

--双目运算符重载为成员函数

--单目运算符重载为成员函数

--运算符重载为非成员函数

-第八章 多态性--运算符重载

-虚函数

--虚函数

--虚析构函数

--虚表与动态绑定

-第八章 多态性--虚函数

-抽象类

--抽象类

--第八章 多态性--抽象类

-override与final

--override与final

-第八章 多态性--override与final

-小结

--第八章小结

-综合实例

--第八章综合实例

-实验八

--实验八

- 第八章讲义

第九章 模板与群体数据

-导学

--导学

-模板

--函数模板

--类模板

-第九章 模板与群体数据--模板

-线性群体

--线性群体的概念

-第九章 模板与群体数据--线性群体

-数组

--数组类模板

--例9-4数组类应用举例

-链表

--链表的概念与结点类模板

--链表类模板

-第九章 模板与群体数据--链表

-栈

--栈类模板

--栈类模板课后习题

--例9-9 栈的应用

--例9-9 栈的应用课后习题

-队列

--队列类模板

-第九章 模板与群体数据--队列

-排序

--排序概述

--插入排序

--选择排序

--交换排序

-第九章 模板与群体数据--排序

-查找

--查找

--查找课后习题

-小结

--小结

-综合实例

--综合实例

-实验九

--实验九

- 第九章讲义

第十章 泛型程序设计与C++标准模板库

-导学

--导学

-泛型程序设计及STL的结构

--泛型程序设计的基本概念

--STL简介

-第十章 泛型程序设计与C++标准模板库--泛型程序设计及STL的结构

-迭代器

--迭代器

-第十章 泛型程序设计与C++标准模板库--迭代器

-容器的基本功能与分类

--容器的基本功能与分类

-第十章 泛型程序设计与C++标准模板库--容器的基本功能与分类

-顺序容器

--顺序容器的基本功能

--顺序容器的特征

--顺序容器的插入迭代器与适配器

--第十章 泛型程序设计与C++标准模板库--顺序容器

-关联容器

--关联容器分类和基本功能

--集合

--映射

--多重集合和多重映射

-第十章 泛型程序设计与C++标准模板库--关联容器

-函数对象

--函数对象

--函数适配器

-算法

--算法

-小结

--第十章小结

-综合实例

--综合实例

-实验十

--实验十

- 第十章讲义

第十一章 流类库与输入/输出

-导学

--导学

-I/O流的概念及流类库结构

--I/O流的概念及流类库结构

-第十一章 流类库与输入/输出--I/O流的概念及流类库结构

-输出流

--输出流概述

--向文本文件输出

--向二进制文件输出

--向字符串输出

-第十一章 流类库与输入/输出--输出流

-输入流

--输入流概述

--输入流应用举例

--从字符串输入

-第十一章 流类库与输入/输出--输入流

-输入/输出流

--输入/输出流

-第十一章 流类库与输入/输出--输入/输出流

-小结

--小结

-综合实例

--综合实例

-实验十一

--实验十一

- 第十一章讲义

第十二章 异常处理

-导学

--第12章导学

-异常处理的思想与程序实现

--异常处理的思想与程序实现

-第十二章 异常处理--异常处理的思想与程序实现

-异常处理中的构造与析构

--异常处理中的构造与析构

-第十二章 异常处理--异常处理中的构造与析构

-标准程序库异常处理

--标准程序库异常处理

-第十二章 异常处理--标准程序库异常处理

-小结

--第12章小结

-综合实例

--综合实例

-实验十二

--实验十二

- 第十二章讲义

异常处理的思想与程序实现笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。