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像素的图片中的手写数字的程序 ...
随机推荐
- wikioi1012 最大公约数和最小公倍数问题(2001年NOIP全国联赛普及组)
题目描述 Description 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数 条件: 1.P,Q是正整 ...
- Linux-CentOS6.4-PXE-DHCP-FTP
DHCP服务器地址:192.168.1.100TFTPfFF服务器地址:192.168.1.100FTP服务器地址:192.168.1.100安装树目录:/var/ftp/pub引导程序目录:/var ...
- python子类分配
原问题是将左边样式变成右边样式: 即有父类和子类,父类包括多个子类,怎样将子类匹配到父类下面的问题 代码如下 #!/usr/bin/python3.4 # -*- coding: utf-8 -*- ...
- ORACLE 包[转]
包的作用: 包可以将任何出现在块声明的语句 ( 过程 , 函数 , 游标 , 游标 , 类型 , 变量 ) 放于包中 , 相当于一个容器 .使用包的好处不仅仅是程序的分组管理,还可以使用包中的程序重载 ...
- MySQL中SSL配置
http://wenku.baidu.com/link?url=Tl71LnP-mqf-HExIRLWviUINgkfHMbd4hL2WGhuUHQlDwcw3QVfuTgcB6CiIMgvszY9W ...
- Hadoop常见错误解决
1. 通过命令和查看日志文件查看hadoop启动和运行情况 在NameNode端,可以通过 tail -100 /var/log/hadoop/hadoop/hadoop-hadoop-namenod ...
- Entity Framework菜鸟初飞
Entity Framework菜鸟初飞 http://blog.csdn.net/zezhi821/article/details/7235134
- Javascript之类型检测
一.检测原始(基本数据:字符串.数字.布尔.null.undefined)类型. 用typeof检测原始类型:1.对于字符串,typeof返回"string"; 2.对于数字,ty ...
- css之四大类选择器
一.选择器: 关于组合选择器之间的区别: 后代选择器(A B)与子选择器(A>B)之间的区别: 后代选择器: 子选择器: 总结:后代选择器的作用范围是一个元素里面包含的所有元素,即包括的是所有的 ...
- Redis启动警告错误解决
启动错误 (1)WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxc ...