我们今天来看下异常处理,在看 C++ 的异常处理之前,先来看看 C 语言中的异常处理。那么什么是异常呢?在程序运行过程中可能会产生异常,异常(Exception)与 Bug 的区别是:异常是程序运行时可预料的执行分支,而 Bug 是程序中的错误,是不被预期的运行方式。
铁东ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联建站的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:028-86922220(备注:SSL证书合作)期待与您的合作!下来我们来看看异常和 Bug 的对比:a> 异常比如运行时产生除 0 的情况,需要打开的外部文件不存在,数组访问时越界;b> Bug 是使用野指针,堆数组使用结束后未释放,选择排序无法处理长度为 0 的数组。在 C 语言中的经典处理方式为:if ... else ... 。if 语句中处理的是正常情况代码逻辑,else 语句中处理的是异常情况代码逻辑。
我们还是以代码为例来看看除法操作异常的处理
#include#include using namespace std; double divide(double a, double b) { const double delta = 0.000000000000001; double ret = 0; if( !((-delta < b) && (b < delta)) ) { ret = a / b; } else { ret = 0; } return ret; } int main() { cout << divide(1, 1) << endl; cout << divide(1, 0) << endl; return 0; }
我们看看编译结果
执行的结果是正确的,但是如果我们打印的是 0/1 的结果呢?我们就不知道执行的到底是正确的情况还是异常的情况。那么我们在上面程序中的 divide 函数中添加一个参数,用来表示执行结果的正确与否,根据这个参数的值来判断执行是否正常。程序如下
#include#include using namespace std; double divide(double a, double b, int* valid) { const double delta = 0.000000000000001; double ret = 0; if( !((-delta < b) && (b < delta)) ) { ret = a / b; *valid = 1; } else { *valid = 0; } return ret; } int main() { int valid = 0; double r = divide(1, 0, &valid); if( valid ) { cout << "r = " << r << endl; } else { cout << "Divided by zero..." << endl; } return 0; }
我们来看看编译结果
再来试试 0/1 呢
我们看到结果已经正确的执行了。但是这个程序有个缺陷,便是 divide 函数需要 3 个参数,难以理解它的用法,而且 divide 函数调用后必须判断 valid 代表的结果,当 valid 为 true 时,运算结果正常;当 valid 为false 时,运算结果出现异常。在 C 语言还有一种异常处理的方式,通过 setjmp() 和 longjmp() 进行判断。下来我们来讲讲这两个函数的原型及其意思:a> int setjmp(jmp_buf env) 是将当前上下文保存在 jmp_buf 结构体中;b> void longjmp(jmp_buf env, int val) 从 jmp_buf 结构体中恢复 setjmp() 保存的上下文,最终从 setjmp 函数调用点返回,返回值为 val;下来我们通过示例代码来进行分析
#include#include #include using namespace std; static jmp_buf env; double divide(double a, double b) { const double delta = 0.000000000000001; double ret = 0; if( !((-delta < b) && (b < delta)) ) { ret = a / b; } else { longjmp(env, 1); } return ret; } int main() { if( setjmp(env) == 0 ) { double r = divide(1, 0); cout << "r = " << r << endl; } else { cout << "Divided by zero..." << endl; } return 0; }
在它进入 main 函数的 if 语句后,会将 0 保存在当前的 env 中,然后 setjmp 函数会保存当前的上下文信息。然后执行 divide 函数,进入到 divide 函数中,会进入到 else 分支。longjmp 函数则会将 1 保存到 env 中并将程序的执行流跳转到 setjmp 处,此时 env 为 1,因此条件不成立,所以会打印出 Divided by zero...,我们来看看编译结果
我们再来看看 1/1 呢,进入到 divide 函数中,它会执行 if 语句进行正常的计算之后直接便会返回 ret,便会输出结果
虽然这是两个参数,但是它有一定的缺陷。setjmp() 和 longjmp() 的引入就必然涉及到使用全局变量,暴力跳转导致代码的可读性降低,其本质还是 if ... else ... 异常处理方式。它的暴力跳转会破坏 C 语言的结构化特性(顺序执行、选择执行、循环执行)。C 语言中的经典异常处理方式会使得程序中逻辑混入大量的处理异常的代码。正常逻辑代码和异常处理代码混合在一起,导致代码迅速膨胀,难以维护。那么在 C++ 中肯定便会有更好的异常处理方式,我们后面会继续学习。通过对 C 语言中异常处理的学习,总结如下:1、程序中不可避免的会发生异常;2、异常是在开发阶段就可以预见的运行时问题;3、C 语言中通过经典的 if ... else ... 方式处理异常,在 C++ 中存在更好的异常处理方式。
欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
售后响应及时
7×24小时客服热线数据备份
更安全、更高效、更稳定价格公道精准
项目经理精准报价不弄虚作假合作无风险
重合同讲信誉,无效全额退款