C++学习39 异常处理入门(try和catch)
编译器能够保证代码的语法是正确的,但是对逻辑错误和运行时错误却无能为力,例如除数为 0、内存分配失败、数组越界等。这些错误如果放任不管,系统就会执行默认的操作,终止程序运行,也就是我们常说的程序崩溃(Crash)。
优秀的程序员能够从故障中恢复,或者提示用户发生了什么;不负责任的程序员放任不管,让程序崩溃。C++提供了异常机制,让我们能够捕获逻辑错误和运行时错误,并作出进一步的处理。
一个程序崩溃的例子:
#include <iostream>
using namespace std;
int main(){
string str = "c plus plus";
char ch1 = str[]; //下标越界,ch1为垃圾值
cout<<ch1<<endl;
char ch2 = str.at(); //下标越界,抛出异常
cout<<ch2<<endl;
return ;
}
运行代码,在控制台输出 ch1 的值后程序崩溃。下面我们来分析一下。
at() 是 string 类的一个成员函数,它会根据下标来返回字符串的一个字符。与“[ ]”不同,at() 会检查下标是否越界,如果越界就抛出一个异常(错误);而“[ ]”不做检查,不管下标是多少都会照常访问。
上面的代码中,下标 100 显然超出了字符串 str 的长度。由于第 6 行代码不会检查下标越界,虽然有逻辑错误,但是程序能够正常运行。而第 8 行代码则不同,at() 函数检测到下标越界会抛出一个异常(也就是报错),这个异常本应由程序员处理,但是我们在代码中并没有处理,所以系统只能执行默认的操作,终止程序执行。
捕获异常
在C++中,我们可以捕获上面的异常,避免程序崩溃。捕获异常的语法为:
try{
// 可能抛出异常的语句
}catch(异常类型){
// 处理异常的语句
}
try 和 catch 都是C++中的关键字,后跟语句块,不能省略“{ }”。try 中包含可能会抛出异常的语句,一旦有异常抛出就会被捕获。从“try”的意思可以看出,它只是“尝试”捕获异常,如果没有异常抛出,那就什么也不捕获。catch 用来处理 try 捕获到的异常;如果 try 没有捕获到异常,就不会执行 catch 中的语句。
修改上面的代码,加入捕获异常的语句:
#include <iostream>
using namespace std;
int main(){
string str = "c plus plus"; try{
char ch1 = str[];
cout<<ch1<<endl;
}catch(exception e){
cout<<"[1]out of bound!"<<endl;
}
try{
char ch2 = str.at();
cout<<ch2<<endl;
}catch(exception e){
cout<<"[2]out of bound!"<<endl;
}
return ;
}
可以看出,第一个 try 没有捕获到异常,输出了一个垃圾值。因为“[ ]”不会检查下标越界,不会抛出异常,所以即使有逻辑错误,try 什么也捕获不到。
第二个 try 捕获到了异常,并跳转到 catch,执行 catch 中的语句。需要说明的是,异常一旦抛出,会立即被捕获,而且不会再执行异常点后面的语句。本例中抛出异常的位置是第 15 行的 at() 函数,它后面的 cout 语句不会再被执行,也就看不到输出。
异常类型
所谓抛出异常,实际上是创建一份数据,这份数据包含了错误信息,程序员可以根据这些信息来判断到底出了什么问题,接下来该怎么处理。
异常既然是一份数据,那么就应该有数据类型。C++规定,异常类型可以是基本类型,也可以是标准库中类的类型,还可以是自定义类的类型。C++语言本身以及标准库中的函数抛出的异常,都是 exception 类或其子类的类型。也就是说,抛出异常时,会创建一个 exception 类或其子类的对象。
异常被捕获后,会和 catch 所能处理的类型对比,如果正好和 catch 类型匹配,或者是它的子类,那么就交给当前 catch 块处理。catch 后面的括号中给出的类型就是它所能处理的异常类型。上面例子中,catch 所能处理的异常类型是 exception,at() 函数抛出的类型是 out_of_range,out_of_range 是 exception 的子类,所以就交给这个 catch 块处理。
catch 后面的exception e
可以分为两部分:exception 为异常类型,e 为 exception 类的对象。异常抛出时,系统会创建 out_of_range 对象,然后将该对象作为“实参”,像函数一样传递给“形参”e,这样,在 catch 块中就可以使用 e 了。
其实,一个 try 后面可以跟多个 catch,形式为:
try
{
//可能抛出异常的语句
}
catch (exception_type_1)
{
//处理异常的语句
}
catch (exception_type_2)
{
//处理异常的语句
}
// ……
catch (exception_type_n)
{
//处理异常的语句
}
异常被捕获时,先和 exception_type_1 作比较,如果异常类型是 exception_type_1 或其子类,那么执行当前 catch 中的代码;如果不是,再和 exception_type_2 作比较……依此类推,直到 exception_type_n。如果最终也没有找到匹配的类型,就只能交给系统处理,终止程序。
多个 catch 块的例子:
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
//自定义错误类型
class myType: public out_of_range{
public:
myType(const string& what_arg): out_of_range(what_arg){}
};
int main(){
string str = "c plus plus";
try{
char ch1 = str.at();
cout<<ch1<<endl;
}catch(myType){
cout<<"Error: myType!"<<endl;
}catch(out_of_range){
cout<<"Error: out_of_range!"<<endl;
}catch(exception){
cout<<"Error: exception!"<<endl;
}
return ;
}
try 捕获到异常后和第一个 catch 对比,由于此时异常类型为 out_of_range,myType 是 out_of_range 的子类,所以匹配失败;继续向下匹配,发现第二个 catch 合适,匹配结束;第三个 catch 不会被执行。
需要注意的是:catch 后面的括号中仅仅给出了异常类型,而没有所谓的“形参”,这是合法的。如果在 catch 中不需要使用错误信息,就可以省略“形参”。
C++学习39 异常处理入门(try和catch)的更多相关文章
- 22 C#中的异常处理入门 try catch throw
软件运行过程中,如果出现了软件正常运行不应该出现的情况,软件就出现了异常.这时候我们需要去处理这些异常.或者让程序终止,避免出现更严重的错误.或者提示用户进行某些更改让程序可以继续运行下去. C#编程 ...
- Scala深入浅出实战经典-----002Scala函数定义、流程控制、异常处理入门实战
002-Scala函数定义.流程控制.异常处理入门实战 Scala函数定义 语句结束无分号 定义无参函数 def 函数名称(参数名称:参数类型)[:Unit=]{ 函数体 } 老师的代码 我的实际代码 ...
- Netty学习——Thrift的入门使用
Netty学习——Thrift的入门使用 希望你能够,了解并使用它.因为它是一个效率很高的框架 官网地址:http://thrift.apache.org/ 1.Thrift数据类型 一门技术如果需要 ...
- DBFlow框架的学习笔记之入门
什么是DBFlow? dbflow是一款android高性的ORM数据库.可以使用在进行项目中有关数据库的操作.github下载源码 1.环境配置 先导入 apt plugin库到你的classpat ...
- 从零开始学习JAVA(入门基础)
目录 博主从零开始学习JAVA(入门基础) 1.搭建JAVA开发环境 卸载JDK(未安装的请忽略) 安装JDK 2.编程语言中,何为编译型与解释型 编译型 解释型 3.第一个JAVA应用程序 4.JA ...
- 从零开始学习jQuery (一) 入门篇
本系列文章导航 从零开始学习jQuery (一) 入门篇 一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案, 即使你会使用jQuery也能在阅读中发现些 ...
- python学习笔记--Django入门四 管理站点--二
接上一节 python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...
- WebSocket学习笔记——无痛入门
WebSocket学习笔记——无痛入门 标签: websocket 2014-04-09 22:05 4987人阅读 评论(1) 收藏 举报 分类: 物联网学习笔记(37) 版权声明:本文为博主原 ...
- 腾讯QQ会员技术团队:人人都可以做深度学习应用:入门篇(下)
四.经典入门demo:识别手写数字(MNIST) 常规的编程入门有"Hello world"程序,而深度学习的入门程序则是MNIST,一个识别28*28像素的图片中的手写数字的程序 ...
随机推荐
- 虚拟化之lxc
LXC 中文名称就是 Linux 容器工具,容器可以提供轻量级的虚拟化,以便隔离进程和资源,使用 LXC 的优点就是不需要安装太多的软件包,使用过程也不会占用太多的资源,本文循序渐进地介绍LXC的建立 ...
- svn安装
方法三.无法连接网络的情况(link链接) 1.从官网下载 Site-1.6.5.zip 2.解压Site-1.6.5.zip至${eclipse}PluginsSubclipse-1.6.5.zip ...
- Excel 导入并导出结果集
1.controler代码: /// <summary> /// 导入预归类意见书 /// </summary> /// <param name="upload ...
- 车载凯立德导航地图更新以及DSA数据更新方法
每年升级每次都去重新摸索,1年时间忘完了,遂决定把他写下来,我这就去实验,实验好了来补 第一步: 找最新的凯立德软件和地图版本号 方法:淘宝搜索, 例如:凯立德 2016,搜索结果会出现比如2016 ...
- sql字符串查找大小写敏感相关
select * from table where target_text like "3"; 等价于 select * from table where target_t ...
- 使用原生js写ajax
// 使用原生js 封装ajax // 兼容xhr对象 function createXHR(){ if(typeof XMLHttpRequest != "undefined") ...
- RMAN备份与恢复之spfile
1.备份spfile 有关控制文件及参数文件备份的几种形式: 单独备份控制文件及参数文件 RMAN> backup current controlfile; 备份数据文件时包含控制文件 RMAN ...
- Web前端相关
1)emmet2)prettify3)angularjs4)coffeescript5)bower (nodejs)6)requirejs
- 剑指offer系列23---字符串排列(不是很理解)
[题目]输入一个字符串,按字典序打印出该字符串中字符的所有排列. 例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 结果请按字母顺 ...
- TCP/IP四层模型和OSI七层模型的概念
转:http://blog.csdn.net/superjunjin/article/details/7841099/ TCP/IP四层模型 TCP/IP是一组协议的代名词,它还包括许多协议,组成了T ...