商业转载请联系作者获得授权,非商业转载请注明出处。

一、什么是异常

-异常是程序中可以检测到的不正常的情况。

-示例:被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++异常处理机制的更多相关文章

  1. Java异常处理机制 try-catch-finally 剖析

    Java拥有着强大的异常处理机制,最近初步学习了下,感觉内容还是挺多的,特此来将自己的理解写出来与大家分享. 一. 在Java代码code中,由于使用Myeclipse IDE,可以自动提醒用户哪里有 ...

  2. JAVA 异常处理机制

    主要讲述几点: 一.异常的简介 二.异常处理流程 三.运行时异常和非运行时异常 四.throws和throw关键字 一.异常简介 异常处理是在程序运行之中出现的情况,例如除数为零.异常类(Except ...

  3. 深入理解java异常处理机制

       异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描述各种不同的 ...

  4. C++学习笔记27:异常处理机制

    一.异常处理机制基础 异常的定义 程序中可以检测的运行不正常的情况 异常处理的基本流程 某段程序代码在执行操作时发生特殊情况,引发一个特定的异常 另一段程序代码捕获该异常并处理它 二.异常的引发 th ...

  5. C++中的异常处理机制

    C++中的捕获异常机制catch参数中实参的类型不同,采取的处理方式则不相同,且与普通的函数调用还不一样,具体表现为当抛出异常throw A()或throw obj时,对象会进行一次额外的对象复制操作 ...

  6. 16、java中的异常处理机制

    异常:就是程序在运行时出现不正常情况.异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述.并封装成对象. 其实就是java对不正常情况进行描述后的对象体现. 对于问题的划 ...

  7. Struts——(四)异常处理机制

    在通常的情况下,我们得到异常以后,需要将页面导航到一个错误提示的页面,提示错误信息.利用Stuts我们可以采用两种方式处理异常: 1.编程式异常处理 即我们在Action中调用业务逻辑层对象的方法时, ...

  8. Java面向对象编程之异常处理机制

    一:Java的异常处理机制的优点: 1:把各种不同情况的异常情况分类,使用JAVA类来表示异常情况,这种类被称为异常类.把各种异常情况表示成异常类,可以充分的发挥类的可扩展性和可重用性. 2:异常流程 ...

  9. Java之异常处理机制

    来源:深入理解java异常处理机制 2.Java异常    异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 ...

  10. SpringMVC异常处理机制详解[附带源码分析]

    目录 前言 重要接口和类介绍 HandlerExceptionResolver接口 AbstractHandlerExceptionResolver抽象类 AbstractHandlerMethodE ...

随机推荐

  1. if else 和switch case以及continue,break的区别

    1,if 经常用于做区间判断 或者 固定值: break和continue的使用        break:用来结束循环结构或者switch case        continue:结束此次循环进入 ...

  2. jdk 环境变量配置方法总结

    全部修改在用户变量/系统变量 系统变量→新建 JAVA_HOME 变量 .变量值填写jdk的安装目录(本人是 D:\java\Java\jdk1.8.0_72) 系统变量→寻找 Path 变量→编辑在 ...

  3. css鼠标样式cursor

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. vscode--搭建自动编译sass环境

    一,安装插件及使用步骤 1.vscode安装Live Sass Compiler,由于该插件依赖Live Server ,所以会自动安装Live Server 2.点击vscode底部的Watch m ...

  5. CentOS上javaweb开发环境搭建

    CentOS上javaweb开发环境搭建 安装jdk yum list java* yum install java-1.7.0-openjdk* -y java -version 安装tomcat ...

  6. 记Angular与Django REST框架的一次合作(2):前端组件化——Angular

    注:这是这个系列的第二部分,主要集中在Angular的使用方面.之前使用过AngularJS(Angular 1.x),混在Django的模板中使用,这些页面一般完全是结果展示页.在有Django表单 ...

  7. Unity 特殊文件夹 Assets Resources StreamingAssets Editor Plugins......

    AssetsAssets文件夹是unity项目中放置游戏资源的主文件夹. 该文件夹中的内容将直接反应在编辑器的Project视口中.许多系统API基于该文件夹路径. ResourcesUnity允许你 ...

  8. 7种方法解决移动端Retina屏幕1px边框问题

    在Reina(视网膜)屏幕的手机上,使用CSS设置的1px的边框实际会比视觉稿粗很多.在之前的项目中,UI告诉我说我们移动项目中的边框全部都变粗了,UI把他的设计稿跟我的屏幕截图跟我看,居然真的不一样 ...

  9. 【原创】IE8升级到IE11控制台报错的解决方案

    公司win7 64位 英文版系统,刚从IE8升级到IE11,在我F12准备调试js的时候,竟然发现控制台报错了!天啦撸,顿时慌了有木有! 网上搜索了半天,解决方案如下: http://www.micr ...

  10. VMvare 虚拟网卡vmnet1 and vmnet8

    VMvare 虚拟网卡vmnet1 and vmnet8---------------------------------2013/11/03 在使用VMware Workstation创建虚拟机时, ...