【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前后台异 ...
随机推荐
- jquery获取兄弟元素
按照w3c school的指引,jquery中,要获得一个元素的兄弟,可以用 prev().next()两种方法.顾名思义,prev()获得前一个,next()获得后面一个. 问题是,如果存在前后兄弟 ...
- ora-12541无监听的一种场景
项目上突然出现无法连接Oracle数据库的情况,提示无监听程序. 现象: 查看 listener.ora配置无问题,用Net Configuration Assistant重建监听,NCA也处于假死状 ...
- MongoDB数据库的初识
1,MongoDB是基于分布式文件存储的数据库,有c++语言编写,旨在为WEB应用提供可扩展的高效性能数据存储解决方案. MongoDB是一个介于关系型数据库和非关系数据库之间的产品,是非关系数据库当 ...
- C项目实践--俄罗斯方块(1)
俄罗斯方块游戏是由前苏联科学院计算机中心的工程师阿列克谢.帕基特诺夫发明的一款小游戏. 1.功能需求分析 1.1主要功能 实现三个功能:1.游戏欢迎界面:2.游戏执行功能,包括计算得分:3.游戏结束界 ...
- Delphi全角转半角
function ToDBC( input :String):WideString;varc:WideString;i:Integer;beginc := input;for i:=1 to Leng ...
- LEA指令与MOV指令的区别——发现一本汇编好书
一.汇编语言中PTR的含义及作用mov ax,bx ;是把BX寄存器“里”的值赋予AX,由于二者都是word型,所以没有必要加“WORD”mov ax,word ptr [bx];是把内存地址等于“B ...
- Remove '@override' annotation解决办法
最近刚刚配置了新机器,将原来的代码放在eclipse上执行,总会出现Remove '@override' annotation,如果要一个个手动删除相当麻烦,最后在网上找了一下原因原来是编译器版本的问 ...
- 苹果Instruments/Shark性能调试工具概述
在Mac OS X上你可以使用Gprof这样的UNIX工具用于测试程序性能.当然,Apple也有自己的Profiling Tools,用得比较多的是Shark.10.5里还引入了一个基于DTrace的 ...
- ModelAndView存取数Model、Map、ModelMap
1.从名字上看ModelAndView中的Model代表模型,View代表视图,这个名字就很好地解释了该类的作用.(对应mvc配置,寻找模型,返回视图.) 2.业务处理器调用模型层处理完用户请求后,把 ...
- codeforces round 417 div2 补题 CF 812 A-E
A Sagheer and Crossroads 水题略过(然而被Hack了 以后要更加谨慎) #include<bits/stdc++.h> using namespace std; i ...