什么是异常和异常处理?
异常就是程序运行过程中出现的问题。“异常”问题并不经常出现(按道理来说我们写好的正常的程序是不应该频繁出现异常的);异常处理技术使得我们可以写程序解决出现的异常问题。很多情况下,处理异常就能使程序想没发生过问题一样继续执行(比如:异常不处理或者处理的很差使用过程中发生崩溃、闪退等问题,处理的好的话就可能我们都不知道有异常,程序自己处理解决了,客户端不知道后台发生了异常,客户能正常获得他想要的信息、执行它的功能就可以。);严重的问题也许会导致程序不能继续执行,使用异常处理可以用可控制的方式对用户发出警示,然后在终止程序(这种相比较于软件闪退、崩溃情况会好一些,起码告知了用户程序不能继续执行,提醒一下用户)
异常处理技术使得我们可以编写更健壮、更具有容错性(这里的容错性不是指包容我们程序的错误,而是对用户的容错,比如用户输入错误的信息,除法中输入了除数为0的情况等)的程序,能够处理发生的问题使程序继续执行,或者优雅的终止。
由于上面的问题,所以要思考如何处理异常,将异常处理放在何处。
异常处理技术使我们可以将错误处理的代码从主逻辑中移出,使得程序更清晰,能增强程序的可维护性;
我们可以有选择的处理异常:所有异常、某种特定类型的所有异常、一组相关类型的所有异常(例如属于某个类继承层次体系的异常);
这种灵活性缩小了错误被忽略的可能性,从而使得程序更加健壮;
C++d异常处理机制使我们从项目一开始就很容易地设计异常处理;
何时使用异常处理?
异常处理用于处理同步错误,也就是语句执行时发生的错误;常见的使用异常处理的错误有:数组下标越界、除数为0、输入参数不合法、算术溢出、内存不够引起的内存分配不成功等问题;异常处理不是用于处理异步事件相关的错误的(例如:磁盘读写结束、网络通信到达、点击鼠标或键盘这些与程序的控制流程并行、独立,不适合异常处理);异常处理机制还适用于处理程序与其他软件元素,例如:成员函数、构造函数、析构函数、类交互时出现的问题。
注意:这些软件元素通常并不在内部处理错误,而是使用异常提示程序发生了问题,这就使得每个应用程序可实现个性化的错误处理。(比如说有一个除数为0的问题,底层在处理这种问题的时候他并不知道遇到这种情况该怎么处理,他不能处理这个情况他就会告诉程序,抛出他的异常。)
复杂的应用程序通常由|预定义的软件组件|和|调用预定义组件的应用程序持有的软件组件|构成(注意断句);当软件组件遇到异常问题时,需要一种机制将问题通知给调用者,预定义组件无法事先预见到不同的应用程序打算如何处理异常问题。
解释:函数f根据程序的需求向下调用他所需要用到的函数,各函数一轮一轮向下,然后如果底层的h()遇到了引发异常的问题,他如果处理不了,他就会向上给调用它的g(),如果g()也处理不了,就会在向上,一级一级向上,直至可以处理这个异常的那一步。
异常声明(异常规范)
一个函数显式声明可能抛出的异常,有利于函数的调用者为异常处理做好准备。
慎用异常声明的情况
1.对于带类型参数的函数模板,要尽量避免使用异常声明,因为不同类型对于相同行为的定义不同,抛出的异常也就不同,因而函数模板很难活不可能确定他具现化的函数实体所可能抛出的异常。
2.使用回到函数时
3.系统可能跑出的异常
C++模板类
模板类方便的是编写者,函数重载方便的是使用者,编写者还是要实现不同的重载函数,并没有少写代码。
template:关键词
typename T:表示类型参数
简单的函数中我们大多使用数据作为参数,但是在模板中类型也是可以作为参数的。数据作为参数作用:参与计算、或是其他操作的值是我们定制的参数,那我们可以用不同的参数参与这个函数的操作;类型作为参数:
类模板的作用
使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的类型、某些成员函数的返回值,能取“任意”类型(包括基本类型和用户自定义的类型)
上图的“类名”准确说是“类模板”
上图是为了形象理解才会展示这样的替换,实际上编译原理执行的操作并不会让他们产生冲突,会让他们成功的运行下去
模板与群体数据(就是STL容器)
群体是指由多个数据元素组成的集合体。群体可以分为两个大类:线性群体和非线性群体(联想到数据结构中线性结构和非线性结构)
线性群体中的元素位置排列有序,可以区分为第一个元素、第二个元素等
非线性群体不用位置顺序来标识元素
静态数组具有固定的元素个数,其中的元素可以直接通过下标访问,它的大小在编译时就已经确定,在运行的时候无法更改,vector元素的个数可以在程序运行时改变,类模板实现动态数组。
泛型程序设计的基本概念(也是STL)
编写不依赖于具体数据类型的程序、将算法从特定的数据结构中抽象出来,成为通用的、C++的模板为反省编程程序设计奠定了关键的基础。
示例:
参考文献: 郑莉教授C++语言程序设计-哔哩哔哩