1.C语言处理错误的方式
传统C语言处理错误有两种方式“
1.终止程序,如assert,
缺陷:用户难以接受。
如发生内存错误,除0错误时就会终止程序。
2.返回错误码
缺陷:需要程序员自己去查找对应的错误。
如系统的很多库的接口函数都是通过把错误码放到errno中,表示错误
实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。
比如说 我有一个100w行的代码出现问题了 如果是传统的C语言抛异常的话 我怎么知道具体是哪出错了 而且C语言只有一个返回值 如果多个地方出错 该返回哪个错误呢?
其他错误怎么办呢?
2.C++异常概念
异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误,
(1) throw:当问题出现时,程序会抛出一个异常,这是通过使用throw关键字来完成的。
(2) catch:在您想要处理问题的地方,通过异常处理程序捕获异常.
catch关键字用于捕获异常,可以有多个catch进行捕获。
(3) try: try块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个catch块。
如果有一个块抛出一个异常,捕获异常的方法会使用try和catch关键字。
try块中放置可能抛出异常的代码,try块中的代码被称为保护代码。
3.异常的使用
异常的抛出和匹配原则
1.异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。
2.被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
3.抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。(这里的处理类似于函数的值返回)
4.catch(…)可以捕获任意类型的异常,问题是不知道异常错误是什么。
一般catch(...) 被放到最后 因为如果放到前面会导致一些规范的异常没有被对应的catch捕获!
防止一些不规范的异常抛出 防止因为异常抛出没有被接收导致的的程序终止
5.实际中抛出和捕获的匹配原则有个例外,并不都是类型完全匹配,可以抛出的派生类对象
使用基类捕获,这个在实际中非常实用,我们后面会详细讲解这个。
6.抛出的同一个异常只能被捕获一次
在函数调用链中异常找展开匹配原则
1,首先检查throw本身是否在try块内部,如果是再查找匹配的catch语句。
如果有匹配的,则调到catch的地方进行处理。
2.没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch。
3.如果到达main函数的找,依旧没有匹配的,则终止程序,上述这个沿着调用链查找匹配的catch子句的过程称为找展开。
所以实际中我们最后都要加一个catch()捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止。
4.找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。
我们思考一下 实际中 我们一个项目有问题 我们一般要抛两个信息 1.哪里出错了 2.出了什么问题
所以我们一般抛一个自定义类型 但是这个时候 第二个问题出现了 实际项目中
不同人完成不同的模块 比如网络模块 抛的问题是网络模块特有的
其他模块里面会包含其模块特有的 难道把每个模块的错误放在一起 放在一个自定义类型里面吗?
如果这样做的话 那抛出来的 自定义类型就太大了
实际上 我们一般写一个父类 网络模块 写一个子类的自定义类型 去继承父类的 这样
不同模块有他们自己特有的部分 同时也有父类的 出错位置 以及原因!
当然C++里面也有自己的异常的库
我们在异常的时候还要注意一些问题
比如安全问题和规范问题
异常被捕获的时候可以再被抛出!