• C++的基本哲学是写的不好的代码不能运行,所以和C比较,C++编译时多了很多检查。
  • 但是总是有在运行时候发生的run-time error ,编译时无法预知。
  • 所以需要C++有一些手段让我们知道有一些不正常事情发生了。

如下例

  • 这五句话其实每一句都hidden着危机,都有可能发生 run-time error
  • 这些问题不是程序问题,而是外面情况带来的问题。比如 open the file, 这个文件可能不存在,可能这个文件被另外一个进程打开了并且那个进程说它要独占地打开。也有可能这个文件大小得不到,因为这个文件可能实际上是一个网络流,不是真的文件。也有可能根本不是文件,是个设备,Unix和Windows把外部设备当作文件,并且数据流链接的远端可能还在一直写数据,无法得到文件大小,所以第二个impossible

上图就叫做异常机制。

异常的抛出和捕捉

对C++解决问题比较好的方式是用exception, 当这种情况发生的时候我们抛出一个异常,告诉更上层的人说这儿有一个问题,我不能解决这个问题,你得来出面解决。所以可以用一个keyword叫做throw

比如我们发现一个数组越界了,我们就扔出一个东西,告诉别人这里出问题了。这就叫throw, throw是一个动词,所以如下是一条语句。对于C++来说什么都可以扔,包括object,原始类型都可以


  • 一般会选择想要一个对象, 可以用对象来表达两件事情, 第一个是每个对象有一个class,通过这个class可以知道里面到底发生了什么, 是数组下标越界?还是除以0?, 第二个是对象本身可以携带data, 可以告诉我们里面到底发生了什么, 比如导致异常发生的index到底是什么?这样外界就可以得知:里面发生的事情是数组越界并且越界下标是-1。

上图:前面的那个class叫做VectorIndexError, 用index来构造那个对象, 于是里面带着index, 这样外面就知道里面发生的问题叫做VectorIndexError, 带的data就是那个出问题的index。

我们扔出去的那个VectorIndexError这个对象在哪里(或者说throw出去的是什么?)?
C++有如下三个地方放对象

  • 什么东西在堆栈里? 本地变量,在函数内部产生的对象
  • 什么东西在堆里? 有且仅有new出来的东西可以再堆里
  • 什么东西在全局数据区在哪里? 全局变量,static本地变量, 静态成员变量。

如上图 在throw后面是个构造函数的调用,所以是在函数内部产生了一个对象,所以在堆栈里。throw要做的事情是这个函数要终止, 要结束, 要离开这个函数,

  • 情况1:有一个函数func,里面做了个12个int的Vector,
  • 用到v[42] out of range,这个时候意味着我对v[42]的调用会发生一个异常, 在上上张图函数里面会发生异常, 那句异常抛出来就意味着throw以下这个函数所有语句都不会执行。然后会离开

这个函数,回到调用它的地方, 就是回到了上图那个func,原则很简单:一旦有一个异常发生,它就检查这句throw所在的那个大括号是什么, 这句throw所在大括号是if语句, 这就意味着这个if语句下面语句不会执行。于是整条if语句相当于一个throw, 再去看这条if语句外面的大括号是什么, 是那个函数。if语句意味着下面不会被执行,它要离开函数,回到被调用的地
方。于是回到了 int i = v[42] 这一句话。意味着** int i = v[42] **相当于一条throw, 继续看它所处的大括号是fun函数, 它就必须离开这个函数, 这个函数接下去语句不会执行,它继续带着VectorIndexError这个对象离开这个fun函数。(如何带着那个对象?只要有那个object地址就可以了),然后回到调用func的地方,如下图

加粗样式

上图意味着func那句函数调用相当于throw了, 因此所在try大括号下面的func2不会被执行

  • try与catch配对, 它现在不着急离开,要看后面的catch有没有能够捕捉到它的。这个catch捕捉的是VectorIndexError的reference, 任何一个对象都可以交给它对应类型的reference的变量, 这就意味着catch在申明说它能够捕捉VectorindexError。 于是我们离开了try, 进入了catch,去做catch里面的事情。做完以后不会try。

最后那个不带任何东西的throw的意思是说:要把刚刚不捕捉到的那个异常对象再抛出去, 这样的话就相当于整句try相当于一句throw, 这个函数又要被打断,又要回到调用它的地方, 这叫做异常的传播(propagate),

catch(…)意味着这个catch能够抓到所有的异常, 但拿不到异常对象, 所以如果不是万般无奈,不用这个

它会沿着调用一直回去,直到找到地方能够处理它的具有try和匹配catch的地方为止。

为什么有的时候要在catch里面还要再throw一下呢?

可能是现在处理它的层级不够, 我知道事情发生了,但只能记录和做一些小小的调整,但还需要让更高的层次来解决问题。

Exceptions最常用的地方就是输入输出。

拓展: 发现问题往往实在非常底层的代码, 这些底层代码只做自己最本分的事情。比如有一个函数负责把一串字符串送到远端,但如果中途网络断了,底层代码应该以什么方式告诉在使用电脑的那个人?比如弹出对话框,对话框不应该由底层代码来弹,应该由更高层次的UI 代码来弹出。最底下那个代码只负责发现Exceptions,然后上报。但如果在服务器里面又是另一种方法。如果最底层的代码来做这些事就混淆了界限,应该有一个异常机制把问题传上去,由上层代码解决。就和上面那个例子一样。

对象被catch以后会被恰当地销毁掉,可以放心

throw + 表达式 表示有个值要抛出去
throw后面不跟任何东西表示要把catch里刚刚收到的异常抛出去。

异常语句

  • try后面至少要有一个catch

**针对每一个catch, 都会运用这些手段。看catch是不是符合其中一个, **



**冒号后面跟上throw(), ()里面可以出现1到多个类,用逗号分隔,这个是用来告诉别的程序说在abc这个函数里头运行时刻,它最多只会抛出圆括号里面那些类(异常), 这是用来约束abc行为的,如果abc抛出别的异常,那么会出现error **

  • 如果 void abc(int a) : throw();//throw括号内没有东西是保证不抛出任何异常
  • 下图例子

failure 异常

如果new得不到足够space是给你一个异常而不是返回NULL(C language)

如果在构造函数内出现异常?

出现一个问题,构造函数自己解决不了,怎么告诉调用构造函数的人出问题了?

PS:构造函数在创建本地变量时自动调用

比较好的方式就是抛一个异常,但如果抛异常的话,意味着构造的对象未完成,析构函数不会调用。并且如果在构造函数里面抛异常,别人拿不到那个对象。

*现在在new的过程当中抛了异常,意味着A p = new A() 做不下去, 意味着p根本没得到, 但是内存已经分配了(new是先分配内存, 先有了内存然后执行构造函数, 把这个内存的地址交给构造函数,然后构造函数构造它)**内存已经有了在堆栈里面, 这就成为内存垃圾了,(空间已经分配了, 没有任何人知道空间在哪里, 无法delete它, 所以变成垃圾了)

所以在构造函数里面抛异常是很大风险的,

解决方法如下图

在抛异常以前把自己删了, 当然这个时候析构没做,但是空间收回了

这个时候那1024个字节就成了内存垃圾。

如上图是指针, catch里面一定要delete它,出了catch没人认识,只能成为内存垃圾了。
这样很复杂,更好的方法如下图。抛的时候抛的是一个堆栈里面的对象(它会在上面)

C++12 Exceptions(异常)相关推荐

  1. PHP 错误与异常 笔记与总结(12 )异常

    ① 异常的概念:异常和错误的区别 PHP 部分借鉴了 C++ 和 JAVA 中的异常处理机制.PHP 中的异常是指 程序运行和预期不太一致,与错误是两个不同的概念. ② 异常的语法结构 [例1] 1 ...

  2. konga 连接postgresql 12+启动异常:error: column r.consrc does not exist

    mac 环境下,konga 配合postgresql 启动,异常如下: A hook (`orm`) failed to load! error: column r.consrc does not e ...

  3. Primavera P6 Professional 21.12 登录异常案例分享

    前不久一个好友咨询P6 Professional 登录异常的问题,因该问题比较特殊,现分享给大家,希望为遇到类似问题的同行/用户提供参考 先介绍P6安装基本信息: APP服务器(App):Weblog ...

  4. python exceptions怎么用_Python基础介绍 | Exceptions异常

    想到本科时候学的Java,各种思想思路,但就是实践得少了,所以讲了也生疏,但让自己静静地敲一敲,你也就明白程序语言里没啥新鲜事. 今天来讲讲程序中的异常: 出现问题时会引发异常.例如,如果你尝试除以零 ...

  5. microsoft.ACE.oledb.12.0异常解决(亲测有效)

    [.net]未在本地计算机上注册"microsoft.ACE.oledb.12.0"提供程序解决办法 报错: 正文:废话不多说,我在网上找了一大批的教程,都在说要下载一个微软的20 ...

  6. 图像检测系列之(12)异常检测(13)拼接伪造(14)deepfake | ICCV2021生成对抗GAN汇总梳理...

    (1)GAN改进系列 | 最新ICCV2021生成对抗网络GAN论文梳理汇总 图像编辑系列之(2)基于StyleGAN(3)GAN逆映射(4)人脸 (5)语义生成 | ICCV2021生成对抗GAN梳 ...

  7. Exceptions 异常

    ※ 前言 尽管人人都希望所处理的事情能顺利进行,所操纵的机器能正常运转,但在现实生活中总会遇到各种异常情况.例如职工小王开车去上班,在正常情况下, 小王会准时到达单位.但是天有不测风云,在小王去上班时 ...

  8. Think in Java第四版 读书笔记6第12章 异常处理

    12.1 概念 异常可以将"在正常时候执行的代码"和"发生错误时的代码"相分离,达到结构清晰的目的. a.受检查异常checkedException 编译器强制 ...

  9. try catch异常后会执行后面的代码吗_JVM异常处理最强讲解

    各种编程语言都有自己的异常捕获.处理方式.在程序指令执行过程中,可能会发生可预知或不可预知的各种异常.通过异常捕获和处理可以记录相关异常日志,执行一些补救策略,让局部的错误不影响服务整体可用性. 那么 ...

最新文章

  1. python客户端和服务端区别_Python socket 客户端和服务器端
  2. STM32如何查找hardfault原因
  3. 关于将struts2框架下,使自定义过滤器对部分的action(一个action或多个action)请求忽略的方法
  4. 简单的一个用javascript做的'省市区'三级联动效果
  5. php v9搜索不到内容,關於如何解決PHPCMS V9內容搜索顯示不全問題解決方案
  6. Echarts官网Json获取方式
  7. 上交所、深交所证券代码编码规则
  8. 苹果电脑装系统只有W ndows,苹果MAC电脑双系统教程——MAC安装Windows双系统教程...
  9. 电磁学matlab仿真实验报告,利用MATLAB语言处理电磁学实验.doc
  10. 知识表示-马尔科夫链(MC)
  11. 大觉寺-阳台山穿越记
  12. eaxyexcel获取指定行,获取总行数
  13. Unity3D点击按钮改变材质球颜色
  14. deepin删除应用程序中图标
  15. c语言中ifelse语句的例子,ifelse语句例子
  16. android多个微信支付,想用快速开关一键收付款?Android 版微信没适配但你可以自己做...
  17. 2022-2028全球及中国食品加工机械行业研究及十四五规划分析报告
  18. 偷学三太子敖丙的功力
  19. Css3制作三角形图标
  20. springboot如何在接收和返回json时下划线转驼峰以及驼峰转下划线

热门文章

  1. debain 自定义快捷键(Ctrl + Alt + T :打开终端)
  2. 智能变电站SCD文件解析虚端子软压板增加描述信息
  3. 查看windows10是否永久激活
  4. java.net.NoRouteToHostException: No route to host (Host unreachable)
  5. 选择什么样的物联网卡才靠谱?
  6. Docker系列之搭建集群版Redis
  7. QUIC详解(转载)
  8. 渗透测试实验一#NMAP#WinHex#Zoomeye
  9. 主机电源所有接口详解
  10. JTS 空间数据关系分析