【C++】异常简述(二):C++的异常处理机制
上文简述了在C语言中异常的处理机制,本文主要讲解C++中的异常处理.
一、异常的语法格式
在C++中,异常的抛出和处理主要使用了以下三个关键字:try、 throw 、 catch.其格式如下:
当我们在程序中想抛出一个异常时,可以这样:
#include<iostream>
#include<exception>
using namespace std;
int Div(int left,int right){
if(right==0){
throw exception("除数不能为0");
}
return left/right;
}
当我们想使用这个函数时,需要在函数外部进行异常的捕获:
int main(){
try{
Div(10,20); //合法
Div(10,30); //合法
Div(10,0); //非法,会抛出异常
}catch(exception & e){
e.what(); //打印异常信息
}
return 0;
}
如果存在不同类型的异常,我们可以这样:
try{
//包含可能抛出异常的语句;
}catch(类型名 [形参名]){
//可能出现的异常1
}catch(类型名 [形参名]){
//可能出现的异常2
}catch(...){
//如果不确定异常类型,在这里可以捕获所有类型异常!
}
二、异常抛出与捕获
1.异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪部分代码.
就上述代码来说,我们throw了一个exception对象,因此在捕获异常时,最终会匹配到catch到exception的代码块.
2.被选中的处理代码是调用链中与该对象类型匹配且离抛出位置最近的那个.
当try内的代码块出现异常时,系统会根据catch的顺序和参数的匹配程度来选择执行哪个代码块,因此,系统会选择最靠前且参数越匹配的代码块.
3. 抛出异常后会释放局部存储对象,所以被抛出的对象也就还给系统了,throw表达式会初始化一个抛出特殊的异常对象副本(匿名对象),异常对象由编译管理,异常对象在传给对应的catch处理之后撤销。
也就是说,在上述的除法代码中,我们throw出的对象在抛出异常后会还给操作系统,而throw表达式会自己初始化一个匿名的对象副本,在传给catch相应的代码块后被回收.
三、栈展开
当我们的程序抛出异常时,会先暂停当前函数的执行,开始查找对应匹配的catch语句.
首先会检查throw是否在代码块内部.
如果是的话,再去找匹配的catch子句.
如果有匹配的,则进行处理.
如果没有,则退出当前函数栈,继续在调用函数的栈中进行从查找.
不断重复上述过程.
如果到达main函数栈,依旧没有匹配,则直接终止程序.
上述沿着调用链查找匹配的catch子句的过程称之为栈展开.
找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行.
四、异常捕获的匹配规则
异常对象类型与catch说明符的类型必须完全匹配,只有以下几种情况例外:
1.允许从非const对象到const类型对象的转换.
2.允许派生类型到基类类型的转换.
3.将数组转换为指向数组类型的指针,将函数转换为指向函数的指针.
五、异常规范
在函数声明之后,列出该函数可能抛出异常类型,并保证该函数不会抛出其他类型的异常.
1、成员函数在类内声明和类外定义两处必须有相同的异常规范.
2、函数抛出一个没有被列在它异常规范中的异常时(且函数中抛出异常没有在函数内部进行处理),系统调用C++标准库中定义的函数unexpected().
3、如果异常规范为throw(),则表示不得抛出任何异常,该函数不用放在try块中.
4、派生类的虚函数的异常规范必须与基类虚函数的异常规范一样或更严格(是基类虚函数的异常的子集).
(因为派生类的虚函数被指向基类类型的指针调用时,保证不会违背基类成员函数的异常规范.)
六、异常与构造&析构函数
1. 构造函数完成对象的构造和初始化,需要保证不要在构造函数中抛出异常,否则可能导致对象不完整或没有完全初始化.
2. 析构函数主要完成资源的清理,需要保证不要在析构函数内抛出异常,否则可能导致资源泄漏(内存泄漏、句柄未关闭等).
七、自定义异常类型
自定义异常类型代码:
class Exception : public exception{
public:
Exception(int errId = 0,const char* errMsg = "")
:_errId(errId)
,_errMsg(errMsg){}
public:
virtual const char* what()const{
cout<<"errId:"<<_errId<<endl;
cout<<"errMsg:"<<_errMsg.c_str()<<endl;
return _errMsg.c_str();
}
private:
int _errId;
string _errMsg;
}
测试代码:
void TestException(){
throw Exception(1,"错误!");
}
int main(){
try{
TestException();
}catch(exception &e){
e.what();
}
}
关于C++异常处理这一块的知识暂时先整理到这里,感谢各位读者支持!
【C++】异常简述(二):C++的异常处理机制的更多相关文章
- springMVC源码分析--异常处理机制HandlerExceptionResolver执行原理(二)
上一篇博客springMVC源码分析--异常处理机制HandlerExceptionResolver简单示例(一)中我们简单地实现了一个异常处理实例,接下来我们要介绍一下HandlerExceptio ...
- 分享知识-快乐自己:Spring中的(三种)异常处理机制
案例目录结构: Web.xml 配置: <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application ...
- 【C++】异常简述(一):C语言中的异常处理机制
人的一生会遇到很多大起大落,尤其是程序员. 程序员写好的程序,论其消亡形式无非三种:无疾而终.自杀.他杀. 当然作为一名程序员,最乐意看到自己写的程序能够无疾而终,因此尽快的学习异常处理机制是非常重要 ...
- Java异常处理机制及两种异常的区别
java异常处理机制主要依赖于try,catch,finally,throw,throws五个关键字. try 关键字后紧跟一个花括号括起来的代码块,简称try块.同理:下面的也被称为相应的块. ...
- 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)
在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...
- Java -- 异常的捕获及处理 -- Java的异常处理机制
7.1.4 Java的异常处理机制 在整个Java的异常处理中,实际上也是按照面向对象的方式进行处理,处理的步骤如下: ⑴ : 一旦产生异常,则首先会产生一个异常类的实例化对象. ⑵ : 在try语句 ...
- Atititjs javascript异常处理机制与java异常的转换.js exception process
Atititjs javascript异常处理机制与java异常的转换.js exception process 1. javascript异常处理机制 Throw str Not throw err ...
- Atitit.js javascript异常处理机制与java异常的转换 多重catc hDWR 环境 .js exception process Vob7
Atitit.js javascript异常处理机制与java异常的转换 多重catc hDWR 环境 .js exception processVob7 1. 1. javascript异常处理机制 ...
- Atitit.js javascript异常处理机制与java异常的转换.js exception process Voae
Atitit.js javascript异常处理机制与java异常的转换.js exception processVoae 1. 1. javascript异常处理机制 1 2. 2. Web前后台异 ...
随机推荐
- POJ1458 Common Subsequence —— DP 最长公共子序列(LCS)
题目链接:http://poj.org/problem?id=1458 Common Subsequence Time Limit: 1000MS Memory Limit: 10000K Tot ...
- get the default proxy by Powershell
https://stackoverflow.com/questions/571429/powershell-web-requests-and-proxies $proxyAddr = (get-ite ...
- javascript 省、市、地县三级联动
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD&g ...
- 并不对劲的bzoj4816:loj2000:p3704[SDOI2017]数字表格
题目大意 有函数\(f(x)\),\(f(0)=0,f(1)=1,f(x)=f(x-1)+f(x-2)\) \(t\)(\(t\leq1000\))组询问,每次给定\(n,m\)(\(n,m\leq1 ...
- sql 指删除表,改表名,改字段名
删除表: DECLARE @Table NVARCHAR(30) DECLARE tmpCur CURSOR FOR SELECT name FROM sys.objects WHERE TYPE=' ...
- asp.net Identity2 角色(Role)的使用(三)用户管理,用户控制器和视图
修改用户控制器AccountController,增加角色管理器. public class AccountController : Controller { public AccountContro ...
- Gym 100548K Last Defence (数论)
题意:给定两个数,然后从第三个开始,每个数都是前两个数的差的绝对值,问这个序列中有多少个不同的元素. 析:这个和辗转相除法差不多,假设a > b那么a-b之间就有a/b个数,然后再计算a%b- ...
- tyvj 1666 城市建设【最小生成树】
-Wall是个好东西,要不然我至死都看不出来我把(b[i]+b[j])写成了(b[i],b[j])-- 还是来自lyd的题解: (其实原来课件第一行式子写错了没有-1,然而我用sai手画了一个上去hh ...
- bzoj 2750: [HAOI2012]Road【spfa+dfs】
枚举起点做spfa,然后一条边在最短路上的条件是dis[e[i].to]==dis[u]+e[i].va,所以每次spfa完之后,dfs出a[i]表示经过i点的最短路的起点数,b[i]表示经过i点的最 ...
- [App Store Connect帮助]八、维护您的 App(4.4)重置 App 总评分(iOS、Apple TVOS、macOS)
当您发布新版本时,您可以重置 App 评分.您的产品页将显示一则消息,说明 App 的总评分最近已重置.此消息将一直显示,直到有足够多的顾客对新版本进行了评分且页面出现新的总评分. 评分只可以针对全球 ...