当前位置: 首页 > news >正文

C++基础语法:异常处理(三)

前言

      "打牢基础,万事不愁" .C++的基础语法的学习."学以致用,边学边用",编程是实践性很强的技术,在运用中理解,总结.

引入

        在编写程序时,可能会因为程序错误或者编译问题等出现异常,因此设计了异常处理机制来应对.以<C++ Prime Plus> 6th Edition(以下称"本书")内容做参考.C++基础语法:异常处理(二)-CSDN博客是本贴的前一篇

内容概览

        异常特性,exception类,异常和继承,异常注意事项

异常特性

        1>控制权转移 

        本书P629 虽然throw-catch机制类似于函数参数和函数返回机制,但还是有些不同之处。其中之一是函数fun( )中的返回语句将控制权返回到调用fun( )的函数,但throw语句将控制权向上返回到第一个这样的函数:包含能够捕获相应异常的try-catch组合。例如,在程序清单15.12中,当函数 hmeans( )引发异常时,控制权将传递给函数means( );然而,当gmean( ) 引发异常时,控制权将向上传递到main( )。(黑体字是原话)

        ----解读:return语句将控制权返回调用他的函数,而throw语句将控制权返回他使用的catch代码块所在的函数.程序的走向可能因throw()发生改变,不再是main()函数.这通常不会是程序员想看到的情况,看一下程序清单15.12 error5.cpp,mean()的函数定义(本书P628),倒数第三句"throw",在执行完后程序走向转移给了main().因此这个特性只需要注意,不会主动去用.

        2>catch后的形参如果是类对象,类型采用对象的引用类型.

        记住这样用就行.在函数重载中,使用变量作形参和使用变量引用作形参,不构成重载.因此用在异常中catch语句的时候只能二选一,选择引用类型.

        还需要记住的有以下两点:

        1.将引发异常和创建对象组合在一起将更简单.本书P629倒数第二段

        也就是throw后调用异常类的构造函数,写法如: throw problem();   //创建problem对象并抛出

        2.本书P630讲了一种场景:catch后面的异常类之间有继承关系的时候,处理异常函数中从上到下依次是基类对象和派生类对象.catch后面从下往上依次是基类对象和派生类对象.

        原因是基类引用可以接收派生类对象.而派生类引用只能接收派生类对象以及用派生类作基类的派生类对象.

        3>catch后跟(...)表示捕获任何异常 

        用法:放在最后一个catch块中,三个省略号表示任何异常被捕获.

异常特性小结

         第2-1条比较常用,其他用得不多.第1条控制权转移,不要让程序跟着throw走,要回到main()中.第3条捕获任何异常,表示编写程序的人自己都不知道会发生什么,也不太适合.

exception类

         C++异常的主要目的是为设计容错程序提供语言级支持即异常使得在程序设计中包含错误处理功能更容易,以免事后采取一些严格的错 误处理方式。异常的灵活性和相对方便性激励着程序员在条件允许的情 况下在程序设计中加入错误处理功能。总之,异常是这样一种特性:类似于类,可以改变您的编程方式。 较新的C++编译器将异常合并到语言中。例如,为支持该语言, exception头文件(以前为exception.h或except.h)定义了exception类, C++可以把它用作其他异常类的基类。代码可以引发exception异常,也 可以将exception类用作基类。有一个名为what( )的虚拟成员函数,它返回一个字符串,该字符串的特征随实现而异 (黑体字是原话)

        ----解读:提供语言级别的支持,语言内定义了exception类,由#include<exception>导入.如果前面的内容只是"开胃菜",那么这是"正菜"了.因为前面的异常类内容需要自己编写,这里的exception类指出在语言的底层给与支持,可以不用自己写异常类,或者可以继承exception类来表达,这种情况下还可以调用名为"what()"的虚成员函数.        

        如果不想以不同的方式处理这些派生而来的异常,可以在同一个基类处理程序中捕获它们:

        以下是经典代码(可以背下来用的),处理一切异常问题,后面的异常内容可以不看了:)

//本书代码
try{...                    //调用可能产生异常的函数(含throw或者字函数含throw
}
catch(std::exception &e){  //用exception对象抓取异常cout<<e.what()<<endl;  //调用what()
}

============================内容分割线==================================== 

        1.除了低头拉车,还要抬头看路.在学习的同时往前往后都看一看.

        是时候反思一下为什么要用异常?什么情况下用异常?

        异常是为了解决被调用的函数可能出错的情况.函数出错的情况是什么?最开始的例子讲了输入参数异常造成逻辑错误是一种,如果程序员编写函数逻辑错误,用try-catch抓取,也看不出来.因此异常处理可以起"流程占位"的作用.对此可以作一个推导:

        把抓取输入异常的两个参数换成"中间结果",即某些函数的返回值,在不知道会不会出错的情况下,推进主程序的编写

        假如要快速搭建一个程序,不管编写的函数有没有问题,先try,完成main()的整个流程,回头再把函数完善.------这是异常的优点

        当然坏处也是显而易见的:第一如果到处都是try,代码难看.另外更主要的是如果一个异常是另一个异常所引起的,不好排查.

        综上所述,尽量让自己熟练写代码,少出错,尽量不用异常处理.前面输入两个参数的异常,可以用以下代码:

//代替异常的代码
int a,b;
while(!(cin>>a>>b&&a+b!=0)){cin.clear();while(cin.get()!='\n');cout<<"请输入两个整数,且不能互为相反数(两个数相加等于0)"
}
....                            //得到两个满足需要的整数,继续程序编写

        2.复习一下类的定义和使用:传入数据(属性),产生逻辑(函数).

        有专门处理异常的类,传入数据作属性,给出异常处理结果.所以类和函数本质上是一样的

============================内容分割线====================================

        空指针和new

          很多代码都是在new在失败时返回空指针时编写的。为处理new的变化,有些编译器提供了一个标记(开关),让用户选择所需的行为。当前,C++标准提供了一种在失败时返回空指针的new

        ----解读:本书明确提到了new分配内存空间的时候容易出错,对于C++而言,用new分配堆空间是常事,所以值得重视,即使不提倡使用异常的情况下.用法:

//本书代码
int *pi=new (std::nothrow) int;
int *pa=new (std::nothrow) int[500];

        以下是经典代码(可以背下来),和程序清单15.13 newexcp.cpp比起来清爽多了

//本书代码
#include<new>
#include<cstdlib>        //for exit(),EXIT_FAILUREBig *pb=new (std::nothrow) Big[10000];    //16亿字节
if(pb==0){cout<<"Could not allocate memory.Bye.\n";exit(EXIT_FAILURE);
}

        含义:如果分配空间失败,退出

小结

        对异常的一些理解

        异常的内容可以深入挖掘,但也可以减减负,等用到的时候再深入

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 一起搭WPF界面之View的简单设计一
  • 文件硬盘数据销毁:守护信息安全的关键一步,文档销毁 数据销毁
  • 【Java】Java 设计模式之工厂模式与策略模式
  • 07 - procfs
  • Java中IO基础文本数据处理:BufferedReader 和 BufferedWriter
  • CSI 插件如何注册到 kubelet 的
  • 【网络基础】探索 NAT 技术:IP 转换、NAPT、NAT穿越及代理服务器
  • Git实战精粹
  • 百度搜索的RLHF性能优化实践
  • APP渠道来源方案探索
  • 在 macOS 上升级 Ruby 版本的几种方法
  • vue事件监听
  • ReentrantLock可重入锁又是怎么回事?
  • CLIP微调方法总结
  • Threejs绘制方形管道
  • Bytom交易说明(账户管理模式)
  • hadoop集群管理系统搭建规划说明
  • iOS | NSProxy
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • java多线程
  • JAVA之继承和多态
  • jquery ajax学习笔记
  • Js基础知识(一) - 变量
  • k8s如何管理Pod
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • php的插入排序,通过双层for循环
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • 前端技术周刊 2019-02-11 Serverless
  • 前端临床手札——文件上传
  • 小程序测试方案初探
  • 一个SAP顾问在美国的这些年
  • 与 ConTeXt MkIV 官方文档的接驳
  • 责任链模式的两种实现
  • #Linux(权限管理)
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (C11) 泛型表达式
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (STM32笔记)九、RCC时钟树与时钟 第一部分
  • (ZT)出版业改革:该死的死,该生的生
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (二)pulsar安装在独立的docker中,python测试
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (论文阅读30/100)Convolutional Pose Machines
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (四)模仿学习-完成后台管理页面查询
  • (转)mysql使用Navicat 导出和导入数据库
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET Framework .NET Core与 .NET 的区别
  • .net 验证控件和javaScript的冲突问题
  • .Net--CLS,CTS,CLI,BCL,FCL
  • .NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.
  • .net项目IIS、VS 附加进程调试