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

一、什么是异常

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

-示例:被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. 来一手 AOP 注解方式进行日志记录

    系统日志对于定位/排查问题的重要性不言而喻,相信许多开发和运维都深有体会. 通过日志追踪代码运行状况,模拟系统执行情况,并迅速定位代码/部署环境问题. 系统日志同样也是数据统计/建模的重要依据,通过分 ...

  2. 【模板小程序】链表排序(qsort/insert_sort/merge_sort)

    前言 本文章整理了链表排序的三种方法,分别是快速排序.插入排序.归并排序.为适应不同用途,先给出常用的int版本,再在此基础上抽象出类模板. 目录 一.针对整数的版本(常用) 文中链表定义 链表相关操 ...

  3. Typescript变量声明

    let 和 const 是 javascript 里面最新的变量声明方式,let 与 var 很相似,而 const 是 let 的增强,能阻止对一个变量的再次赋值. var 声明 弱类型:var 声 ...

  4. Unity 发布的 WebGL 使用SendMessage传递多个参数

    如果要实现Unity与浏览器的数据交互一般都会采用两种方式 方法一: Application.ExternalCall("SayHello","helloworld&qu ...

  5. centos 系统常用命令

    一:查看cpu信息more /proc/cpuinfo | grep "model name" grep "model name" /proc/cpuinfo ...

  6. virtual与static

    virtual与static不能同时作用于一个函数.根据面向对象的理论,virtual的成员函数是可以变子类覆盖的,是实现多态的重要手段.而static作用的成员函数表示该函数仅属于某个类. 下面是实 ...

  7. Charles使用(二)

    Charles使用(二)   破解Charles 找到Charles应用-->右键显示包内容--->contents-->java:更换Charles.jar即可 链接: https ...

  8. nodejs之express4x

    学习node好榜样!前阵子看了php,那个模块化编译真的好棒.然而php学习起来不是一般的记不住,毕竟和js还是有不同的.于是转移到了node.看到熟悉的js脚本,心里踏实多了. 话不多讲,php我也 ...

  9. JavaScript 日期处理类库

    Moment.js  http://momentjs.cn/

  10. tomcat-users.xml配置Manager登陆用户

    添加用来登陆tomcat-manager的用户 <tomcat-users> <!-- NOTE: By default, no user is included in the &q ...