赞
踩
异常是程序在 运行期间 产生的问题,程序可以正常通过编译,没有语法问题,只是由于在运行中触发了一些C++预定义的逻辑问题,从而产生了异常现象。异常是需要正确的处理的,如果没有得到正确处理,则程序运行会终止
●抛出异常 throw
●捕获异常 try-catch
C++底层和程序员都可以抛出异常,例如在下面的代码中,C++底层会抛出一个异常对象,这个异常对象会优先在当前代码寻找处理的措施,当找不到时,会向上转移,直到找到处理的措施,一直向上转移到主函数还找不到处理措施就会运行终止
#include <iostream> using namespace std; void test1() { string s = "23"; cout << s.at(34) << endl; // 抛出异常对象 } void test2() { test1(); } int main() { test2(); cout << "主函数执行结束" << endl; return 0; }
上面的代码运行到第8行,C++底层检测到下标范围越界,会抛出一个异常对象,这个对象首先在第8行寻找处理措施的相关代码,找不到就去上一级第13行寻找,找不到再去第19行寻找,直到主函数还是没有处理这个异常,于是程序运行终止,并输出异常对象携带的相关信息。
除了C++底层固定的一些错误的逻辑操作会抛出异常外,程序员也可以自己制定抛出的时机和抛出的异常对象。因为C++的异常体系不是特别健全,因此如果要在项目中使用异常处理,程序员自身规定一些逻辑错误的情况,并抛出对应的异常对象就显得相对重要了
#include <iostream> using namespace std; double division(double a,double b) { // 手动抛出异常对象 if(b == 0) throw "不能除以0!!!!"; return a/b; } int main() { double d = division(3,0); cout << d << endl; cout << "主函数执行结束" << endl; return 0; }
把可能出现异常的代码放置到try代码块中,在catch代码块中编写对应的处理逻辑。try块中尽量少放代码,非异常代码在try中虽然也可以得到正常执行的,但是效率偏低。
try块必须配合catch块进行异常类型匹配。需要注意的是,catch块如果匹配的类型不一致,整个异常捕获都会失效
#include <iostream> using namespace std; double division(double a,double b) { // 手动抛出异常对象 if(b == 0) throw "不能除以0!!!!"; return a/b; } int main() { try { double d = division(3,0); cout << d << endl; } catch(const char* e) { cout << e << endl; cout << 1 << endl; // 弥补措施 } cout << "主函数执行结束" << endl; return 0; }
上面的代码中,手动抛出的异常类型是char*,这种类型不是推荐的异常类型,一个标准的类型应该从继承结构上属于标准异常家族。
以下是C++标准异常库的相关类型:
使用上面的异常类型需要引入头文件 #include stdexcept(尖括号在scdn文档中会隐藏掉括号中的内容)
标准异常库的类型相对较少,无法覆盖很多开发的情况,程序员可以自定义一个异常类继承标准异常库中异常类型
#include <iostream> #include <stdexcept> using namespace std; class ZeroException:public exception { public: // 覆盖what函数 const char* what() const throw() { return "不能除以0!!!!"; } }; double division(double a,double b) { // 手动抛出异常对象 if(b == 0) throw ZeroException(); return a/b; } int main() { try { double d = division(3,0); cout << d << endl; }catch(const ZeroException& e) { cout << e.what() << endl; // 打印异常信息 cout << 1 << endl; // 弥补措施 } cout << "主函数执行结束" << endl; return 0; }
之所以要自定义异常类型,并继承自标准异常,是因为异常的捕获不光可以匹配精准的类型,也可以匹配粗略的类型(基类)。
异常捕获也支持多重捕获,类似于switch-case,case语句可以若干个,catch语句也可以有若干个。如果使用多重捕获,一定要先捕获派生类异常类型,再捕获基类异常类型,可以认为基类异常类型是一种保底的措施
#include <iostream> #include <stdexcept> using namespace std; class ZeroException:public exception { public: // 覆盖what函数 const char* what() const throw() { return "不能除以0!!!!"; } }; double division(double a,double b) { // 手动抛出异常对象 if(b == 0) throw ZeroException(); return a/b; } int main() { try { double d = division(3,0); cout << d << endl; }catch(ZeroException e) { cout << e.what() << endl; // 打印异常信息 cout << 2 << endl; // 弥补措施 }catch(exception e) { cout << e.what() << endl; // 打印异常信息 cout << 1 << endl; // 弥补措施 } cout << "主函数执行结束" << endl; return 0; }
try-catch块的执行逻辑是:
另外,可以使用…匹配任意异常类型,包括非标准异常库类型
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。