C++异常处理机制
商业转载请联系作者获得授权,非商业转载请注明出处。
一、什么是异常
-异常是程序中可以检测到的不正常的情况。
-示例:被0除、数组越界、存储空间不足等。
-早期我们使用if来判断,然后进行相关处理,或者也可以使用断言。关于异常与断言这里引用了一段解释
关于异常和断言,个人以为,阐述最清楚的当属“契约式编程”。简而言之,检查前条件使用ASSERT,检查后条件使用异常。
以一个函数为例,它要求在开始执行的时候满足一系列条件,这些条件被称为“前条件”或者“先验条件”,比如,参数不为空,某全局变量应该为1,等等。不满足前条件,是不能调用此函数的,如果出现了前条件不满足仍然调用了此函数,可以认为这是一个设计错误。
检查前条件,可以使用ASSERT。这个函数执行以后,也会满足一系列条件,这些条件被称为“后条件”或者“后验条件”,比如返回值满足什么关系,某全局变量设置称为什么什么,等等。这应该是函数执行的结果,在前条件满足的情况下,后条件如果没有满足是一种不正常的情况,那么使用异常来处理。
作者:晨池链接:https://www.zhihu.com/question/24461924/answer/27928436来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
-C++中提供了异常类,提供更加灵活的异常处理手段。
二、异常处理的基本流程
-某段程序代码在执行操作时发生了特殊情况,引发一个特定的异常
-另一段程序捕捉这个异常并处理
//异常类:空栈异常类与满栈异常类
class EStackEmpty{};//空类
class EStackFull{}; int JuStack::Pop()
{
if(IsEmpty())//引发异常
throw EStackEmpty(); //抛出
}
void JuStack::Push(int value)
{
if (IsFull())
throw EStackFull();
}
//异常的捕获
try
{
可能引发异常的函数调用
}
catch(const 一个异常对象的引用) //捕获抛出的异常,执行相应的处理
{
相应处理
}
三、异常类与异常对象
在实际编程中我们一般需要设计异常类,提供必要的异常信息,以便灵活的处理异常。
//构造异常类
class EStackFull
{
public;
EStackFull(int i):_value(i){}
int GetValue(){return _value;}
private:
int _value;
};
void JuStack::Push(int value)
{
if (IsFull())
throw EStackFull(value);//使用value构造异常类对象并抛出异常
_stk[_top] = value;
_top++,_cnt++;
}
int main()//对主程序的修改
{
JuStack stack();
try
{
for (int i=;i < ;i++)
stack.push(i); //如果发生异常,抛出异常
}
catch (const EStackFull & e)//使用异常对象获取详细信息
{
std::cerr<<"Stack full when trying to push"<<e.GetValue()<<std::endl;
return err_stack_full; //异常提示信息
}
return ;
}
四、异常类处理策略
1、异常类可以派生和继承,形成库架构,正常的思维是我们应该有一个顶层的抽象的异常类,然后后续的异常类都应该从这个异常类继承下来,事实上C++标准库已经给我们提供了这样一个异常类,你写的异常类都应该从表中库中的那个异常类继承下来。可捕获的异常对象的形式是需要说明一下的在catch的那个子句中我们可以捕获任何形似的类型,当你以普通形式的形似来捕获的时候,这些异常对象就需要拷贝,你也可以捕获对某形式对象的一个引用,这个时候是没有额外的拷贝动作的,你也可以捕获指向某形式对象的一个指针,不过这时候要求对象动态构造,这样那个指针在catch中才可以访问到。
2、-catch子句中可以封装对这个特定异常的一些必要的处理代码,实际编写程序可以有很多个cache子句,每一个负责捕获一种、一类或者全部异常。
catch(int)、catch(const char*)这一类可以捕获一种异常。catch(const EStackFull &)可以捕获该类或其派生类。catch(...)捕获全部。
在执行的时候所有的catch语句是按照定义的顺序去做的,如果你的异常类有继承层次,那么你要把派生类的catch语句写在前面,把基类的catch语句写在后面,否则派生类异常没有机会执行。
3、-可以在基本任务完成后重新引发所处理的异常
-主要用于在程序终止之前写入日志和实施特殊清除任务
4、栈展开
-异常引发代码和异常处理代码可能属于不同的函数
-当异常发生的时候,沿着异常处理块的嵌套顺序逆向查找能够处理该异常的catch子句
-找到catch子句,处理该异常,异常处理完毕之后,程序保持catch子句所在的函数栈框架,不会返回引发异常的函数栈框架(这就是为什么我们说在异常处理的时候需要按照定义的顺序去做)
-函数栈框架消失了,局部对象被析构,但是如果未执行delete操作,动态分配的目标对象未析构(导致内存泄露)
5、未处理异常
-所有未处理的异常由预定义的sdt::terminate()函数处理
-可以使用std::set_terminate()函数设置std::terminate()函数的处理例程
6、C++11规范中建议使用noexcept代替throw
五、异常描述规范
在编写成员函数时,对于有可能引发异常的函数进行描述,把异常描述写在函数的声明处例如:
public:
int Pop() noexcept(false);//会引发异常
int Push() noexcept; //不会引发异常
int A() noexcept(noexcept(expr)); //可能引发异常expr是可以转化为true或者false的常数表达式
C++异常处理机制的更多相关文章
- Java异常处理机制 try-catch-finally 剖析
Java拥有着强大的异常处理机制,最近初步学习了下,感觉内容还是挺多的,特此来将自己的理解写出来与大家分享. 一. 在Java代码code中,由于使用Myeclipse IDE,可以自动提醒用户哪里有 ...
- JAVA 异常处理机制
主要讲述几点: 一.异常的简介 二.异常处理流程 三.运行时异常和非运行时异常 四.throws和throw关键字 一.异常简介 异常处理是在程序运行之中出现的情况,例如除数为零.异常类(Except ...
- 深入理解java异常处理机制
异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描述各种不同的 ...
- C++学习笔记27:异常处理机制
一.异常处理机制基础 异常的定义 程序中可以检测的运行不正常的情况 异常处理的基本流程 某段程序代码在执行操作时发生特殊情况,引发一个特定的异常 另一段程序代码捕获该异常并处理它 二.异常的引发 th ...
- C++中的异常处理机制
C++中的捕获异常机制catch参数中实参的类型不同,采取的处理方式则不相同,且与普通的函数调用还不一样,具体表现为当抛出异常throw A()或throw obj时,对象会进行一次额外的对象复制操作 ...
- 16、java中的异常处理机制
异常:就是程序在运行时出现不正常情况.异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述.并封装成对象. 其实就是java对不正常情况进行描述后的对象体现. 对于问题的划 ...
- Struts——(四)异常处理机制
在通常的情况下,我们得到异常以后,需要将页面导航到一个错误提示的页面,提示错误信息.利用Stuts我们可以采用两种方式处理异常: 1.编程式异常处理 即我们在Action中调用业务逻辑层对象的方法时, ...
- Java面向对象编程之异常处理机制
一:Java的异常处理机制的优点: 1:把各种不同情况的异常情况分类,使用JAVA类来表示异常情况,这种类被称为异常类.把各种异常情况表示成异常类,可以充分的发挥类的可扩展性和可重用性. 2:异常流程 ...
- Java之异常处理机制
来源:深入理解java异常处理机制 2.Java异常 异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 ...
- SpringMVC异常处理机制详解[附带源码分析]
目录 前言 重要接口和类介绍 HandlerExceptionResolver接口 AbstractHandlerExceptionResolver抽象类 AbstractHandlerMethodE ...
随机推荐
- Object-C 里面的animation动画效果,核心动画
#import "CoreAnimationViewController.h" @interface CoreAnimationViewController ()@property ...
- global,$GLOBALS[' '] 全局, 浮动float跟margin的注意事项
$a; global只能声明变量为全局,不能赋值,否则报错未定义:global $a; 相对于$GLOBALS['a'],写法是这样的,所有定义过的变量都存在这里: //浮动float跟margin的 ...
- 移动APP云测试平台测评分析
随着智能手机的普及率和渗透率越来越高,App开发软件也越来越多.有专家预测,2017年的App应用下载量将会突破2500亿,整个移动科技市场规模将会达到770亿美元.身处在这个"移动&quo ...
- 1. 数字根(Digital Root)
数字根(Digital Root)就是把一个自然数的各位数字相加,再将所得数的各位数字相加,直到所得数为一位数字为止.而这个一位数便是原来数字的数字根.例如: 198的数字根为9(1+9+8=18,1 ...
- Java中synchronized和Lock的区别
synchronized和Lock的区别synchronize锁对象可以是任意对象,由于监视器方法必须要拥有锁对象那么任意对象都可以调用的方法所以将其抽取到Object类中去定义监视器方法这样锁对象和 ...
- Vue模板内容
前面的话 如果只使用Vue最基础的声明式渲染的功能,则完全可以把Vue当做一个模板引擎来使用.本文将详细介绍Vue模板内容 概述 Vue.js使用了基于HTML的模板语法,允许声明式地将DOM绑定至底 ...
- hdu--4148--Length of S(n)
#include<iostream> #include<string> #include<cstring> void priTable(); using names ...
- 分辨率验证工具 - 【Firesizer】的使用
Firesizer是一款测试分辨率的插件. 下载方式:Firefox工具栏——〉工具——〉附加组件--〉搜索Firesizer并安装,浏览器会自动重启 使用方式:浏览器右下角直接切换分辨率即可,如下图 ...
- 诡异错误二:TypeError: data type not understood
如何使用Python产生一个数组,数组的长度为1024,数组的元素全为0? 很简单啊, 使用zeros(1024) 即可实现! 如何产生一个2×1024的全0矩阵呢?是否是zeros(2,1024) ...
- 在WebGL场景中使用2DA*寻路
这篇文章将讨论如何在一个自定义的地面网格上进行简单的2D寻路,以及确定路径后如何使用基于物理引擎的运动方式使物体沿路径到达目标地点.读者需要预先对WebGL和Babylonjs知识有一些了解,可以 ...