经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
深入了解C++异常处理
来源:jb51  时间:2021/12/15 8:46:22  对本文有异议

基本的异常处理

异常处理机制:暂缓问题处理,不在当前函数中处理,在他的调用者中处理(先上车,后补票)

什么是异常:任何东西都可以认为是异常,错误只是异常的一种

异常一旦被抛出,不做处理,如果引发异常,会调用默认abort函数终止程序

捕获和处理异常:

throw 抛出异常: (值是任何类型都可以,只是我们处理异常的一个参照,类似返回值)

try(检查,捕获)和catch(处理异常): 必须是一起出现,并且它们的括号{ }不能省略

tip:? ?任何东西都可以认为是异常,错误只是异常中的一种---出现一种情况不能让程序正常运行

怎么抛出异常

  1. //求a和b的余数 怎么抛出异常
  2. int division(int a,int b){
  3. if(b==0)
  4. throw 0; //抛出一个值(任意)--->之后处理
  5. return a/b;
  6. }
  7. void print(int a,int b){
  8. cout<<division(a,b);
  9. }
  10. int main(){
  11. print(1,0);
  12. }
  13. /* 把b==0 的情况称为异常,b==0 时代码不成立,会调用默认abort函数终止程序 */

异常一旦被抛出,不做处理,如果引发异常,会调用默认abort函数终止程序?

捕获和处理异常

  1. //try 与catch必须是一起出现,并且他们的括号{}不能省略
  2. try
  3. {
  4. //正常需要检查是否存在异常的代码
  5. }
  6. catch(类型) //理解为switch中case语句
  7. {
  8. //处理是根据抛出数据类型决定如何处理 匹配项 匹配抛出异常的类型
  9. }
  10. //一个try可以对应多个catch
  11. try
  12. {
  13. //...
  14. }
  15. catch(int)
  16. {
  17. }
  18. catch(double)
  19. {
  20. }
  21. catch(string)
  22. {
  23. }
  24. //catch和if else_if 执行机制是一样的,只能执行一个匹配项

小知识:

  • 对try{ }? ?catch(){ } 的理解:在当前位置引发异常,直接从这个位置跳到catch的位置执行catch的代码 --- 类似switch case 语句
  • catch中int和char不会做转换
  • 写两个相同的类型不被允许,哪段代码先引发异常就先调用catch
  1. int division(int a,int b){
  2. if(b==0)
  3. throw 0;
  4. return a/b;
  5. }
  6. void print(int a,int b){
  7. cout<<division(a,b);
  8. }
  9. int main(){
  10. try
  11. {
  12. print(1,0); //检查异常
  13. cout<<"别的代码"<<endl; //这一句不会运行,会直接跳到catch
  14. }
  15. catch(int) //抛出的是int类型,捕获int类型
  16. {
  17. cout<<"除数不能为0"<<endl;
  18. }
  19. }

程序能抛出(存在)多个异常,但是只能同时处理1个异常,不能同时引发多个异常

不存在异常的描述 --- 标识性作用? ??

  • throw ()
  • noexcept
  1. //某个函数不存在异常,在某个函数后面用throw() 描述,表示它不存在异常
  2. void print() throw()
  3. {
  4. cout << "当前函数不存在抛出异常操作" << endl;
  5. }
  6. void printData() noexcept
  7. {
  8. cout << "c++新标准中的关键字: 不存在抛出异常操作" << endl;
  9. //throw 0; 一旦说明没有异常操作,就不能抛出
  10. }

删减符 ...

任何类型的异常都捕获? ? 不管抛出啥,在哪里抛出的,只要引发异常都可以捕获到

  1. catch(...)
  2. {
  3. cout <<"捕获任何类型的异常"<< endl;
  4. }

异常处理中的传参操作? --- 可以写一个变量进去

catch(int a)/* 隐藏了一个传参操作 可以传任何类型,包括自定义类型都可以 */

注意c++中string的处理? ? /* string类型与const char* 类型区别 */

代码解析:

对? 通过抛出字符串,隐藏了一个传参操作? 的理解

  1. int divisor(int a, int b)
  2. {
  3. if (b == 0)
  4. throw string("除数不能为0");
  5. return a / b;
  6. }
  7. int main()
  8. {
  9. try
  10. {
  11. divisor(1, 0);
  12. }
  13. catch (string str) //把throw的内容赋值给str str="除数不能为0"
  14. {
  15. cout << str << endl;
  16. }
  17. }

注意string类型与const char* 类型区别? --- 出现类型不匹配,c++对传参类型要求更严格

  1. int divisor(int a, int b)
  2. {
  3. if (b == 0)
  4. throw "除数不能为0"; //抛出异常 解析为char* 类型 写catch时不能直接当作string
  5. if(b==1)
  6. throw "除数不能为1"; /* 不同问题的抛出,不能用固定类型(int、char...), 可以选择
  7. 抛出不同字符串处理 string1,string2,string3... 通过传
  8. 参的方式去描述问题 */
  9. if(b==2)
  10. throw string("除数不能为2"); //需构造无名参数作捕获对象处理--->需要自己触发
  11. return a / b;
  12. }
  13. int main()
  14. {
  15. try
  16. {
  17. divisor(1, 0); //直接触发异常
  18. }
  19. catch (const char* str) //抛出的是char* 类型,不能当作string
  20. {
  21. cout << str << endl;
  22. }
  23. try
  24. {
  25. divisor(1, 2);
  26. }
  27. catch (string str) //如果要捕获string类型,需要自己构造一个string对象返回
  28. {
  29. cout << str << endl; //直接输出str
  30. }
  31. }

可以抛出自己类的对象

  1. class Error
  2. {
  3. public:
  4. Error(const char* str = "未知错误") :str(str) {}
  5. const char* what()const
  6. {
  7. return str.c_str();
  8. }
  9. protected:
  10. string str;
  11. };
  12. void insertArray(int array[], int* curNum, int posData,int maxLength)
  13. {
  14. if (*curNum >= maxLength) //3>=3
  15. {
  16. throw Error("数组下标溢出!");
  17. }
  18. //0 1 2
  19. array[*curNum] = posData; //array[3]=3
  20. (*curNum)++;
  21. }
  22. int main(){
  23. try
  24. {
  25. int array[3] = { 0,0,0 };
  26. int curNum = 0;
  27. for (int i = 0; i < 4; i++)
  28. {
  29. insertArray(array, &curNum, i, 3);
  30. }
  31. }
  32. catch (Error str)
  33. {
  34. cout << str.what() << endl;
  35. }
  36. return 0;
  37. }

标准库当中的异常类

  1. #include<exception> //父类(基类)

子类很多,子类描述的问题不同而已

例子: const char* _ptr; 一个数据成员,用于描述标准库当中异常的字符串,用字符指针存放那个字符串

what( )方法? 用于返回数据成员的? ? ? ? 1.虚函数? ? ? ? 2.不存在异常

return _ptr ? _ptr : "unknow";判断char* 类型的指针是不是为空,不等于空,返回你描述的错误,等于空(由于没有传参),返回未知错误"unknow"

引发标准库中内存申请失败的异常

发现代码出现abort( )错误,可以通过这种方式找到,这里是针对内存申请失败做了单一处理,如果不做处理,会直接调用abort函数终止程序

  1. #include <exception>
  2. #include <iostream>
  3. using namespace std;
  4. class Exception
  5. {
  6. public:
  7. Exception(const char* ptr="UNKNOW") :ptr(const_cast<char*>(ptr)){} /*构造函数 干掉
  8. 常属性*/
  9. virtual const char* what() const //父类是虚函数 且不存在异常
  10. {
  11. return ptr;
  12. }
  13. protected:
  14. char* ptr;
  15. };
  16. //子类继承父类
  17. class Bad_alloc :public Exception
  18. {
  19. public:
  20. Bad_alloc(const char* _Message = "bad exception") :Exception(_Message) {} /*调用父类
  21. 的构造函数抛出bad exception*/
  22. protected:
  23. };
  24. //子类继承父类 调用父类构造函数
  25. class Run_time :public Exception
  26. {
  27. public:
  28. Run_time(const char* _Message = "run_time error") :Exception(_Message) {}
  29. protected:
  30. };
  31. int main()
  32. {
  33. try
  34. {
  35. while (1)
  36. {
  37. int* p = new int[1024*1024*10];//一直做内存申请,不做释放,最后一定会内存申请失败
  38. }
  39. }
  40. catch (bad_alloc& object) /* 内存申请失败,调用bad_alloc 标准库中的异常,创建一个对象接收一
  41. 下,子类中的what()方法调用父类中的what()方法打印 */
  42. {
  43. cout << object.what() << endl;
  44. }
  45. return 0;
  46. }
  47. /*输出*/
  48. bad allocation //调用时抛出 bad allocation 是子类对象调用继承下来的what()方法
  49. //一般写代码出现莫名的中断,原因是不做异常处理,引发了abort函数中断程序,一般这种错误都是特殊错误

标准库中传两个参数起到标识作用,由于:引发了不同的错误,不同错误对应了不同的错误编码 对这些错误有特定的描述 ---> 工具 ---> 错误查找 ---> 输入错误编码

值:3

错误信息:系统找不到指定的路径?

以上就是深入了解C++异常处理的详细内容,更多关于C++异常处理的资料请关注w3xue其它相关文章!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号