类型转换
什么是异常
1)异常是一种程序控制机制,与函数机制独立和互补
函数是一种以栈结构展开的上下函数衔接的程序控制系统,异常是另一种控制结构,它依附于栈结构,却可以同时设置多个异常类型作为网捕条件,从而以类型匹配在栈机制中跳跃回馈.
2)异常设计目的:
栈机制是一种高度节律性控制机制,面向对象编程却要求对象之间有方向、有目的的控制传动,从一开始,异常就是冲着改变程序控制结构,以适应面向对象程序更有效地工作这个主题,而不是仅为了进行错误处理。异常设计出来之后,却发现在错误处理方面获得了最大的好处。
异常的基本语法
1) 若有异常则通过throw操作创建一个异常对象并抛掷。
2) 将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺序执行到达try语句,然后执行try块内的保护段。
3) 如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从try块后跟随的最后一个catch子句后面的语句继续执行下去。
4) catch子句按其在try块后出现的顺序被检查。匹配的catch子句将捕获并处理异常(或继续抛掷异常)。
5)处理不了的异常,可以在catch的最后一个分支,使用throw语法,向上扔。
6)异常机制与函数机制互不干涉,但捕捉的方式是基于类型匹配。捕捉相当于函数返回类型的匹配,而不是函数参数的匹配,所以捕捉不用考虑一个抛掷中的多种数据类型匹配问题
7)异常捕捉严格按照类型匹配
异常捕捉的类型匹配之苛刻程度可以和模板的类型匹配媲美,它不允许相容类型的隐式转换,比如,抛掷char类型用int型就捕捉不到
异常处理思想
1)C++的异常处理机制使得异常的引发和异常的处理不必在同一个函数中,这样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理。上层调用者可以再适当的位置设计对不同类型异常的处理。
2)异常是专门针对抽象编程中的一系列错误处理的,C++中不能借助函数机制,因为栈结构的本质是先进后出,依次访问,无法进行跳跃,但错误处理的特征却是遇到错误信息就想要转到若干级之上进行重新尝试。
3)异常超脱于函数机制,决定了其对函数的跨越式回跳。
4)异常跨越函数
栈解旋
异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反。这一过程称为栈的解旋(unwinding)。
设计一个数组类 MyArray,重载[]操作,
数组初始化时,对数组的个数进行有效检查
1)index<0 抛出异常eNegative
2)index = 0 抛出异常 eZero
3)index>1000抛出异常eTooBig
4)index<10 抛出异常eTooSmall
5)eSize类是以上类的父类,实现有参数构造、并定义virtual void printErr()输出错误。
#include <iostream>
using namespace std;
class MyArray
{
public:
MyArray(int index);
class eSize
{
protected:
int size;
public:
eSize(int size)
{
this->size = size;
}
virtual void printErr() = 0;
};
class eNegative:public eSize
{
public:
eNegative(int size):eSize(size)
{
}
virtual void printErr()
{
printf("小于0:%d\n",size);
}
};
class eZero:public eSize
{
public:
eZero(int size):eSize(size)
{
}
virtual void printErr()
{
printf("等于0:%d\n",size);
}
};
class eTooBig:public eSize
{
public:
eTooBig(int size):eSize(size)
{
}
virtual void printErr()
{
printf("size 大于 1000:%d\n",size);
}
};
class eTooSmall:public eSize
{
public:
eTooSmall(int size):eSize(size)
{
}
virtual void printErr()
{
printf("size 小于 10:%d\n",size);
}
};
};
MyArray::MyArray(int index)
{
if (index < 0)
throw eNegative(index);
if (index == 0)
throw eZero(index);
if (index > 1000)
throw eTooBig(index);
if (index < 10)
throw eTooSmall(index);
}
int main()
{
try
{
MyArray a(5);
}
catch (MyArray::eSize &e)
{
e.printErr(); // 多态
}
return 0;
}
结果:size 小于 10:5
C++的输入输出流
1、I/O流概念
程序的输入指的是从输入文件将数据传送给程序,程序的输出指的是从程序将数据传送给输出文件。
C++输入输出包含以下三个方面的内容:
标准I/O:对系统指定的标准设备的输入和输出。即从键盘输入数据,输出到显示器屏幕。
文件I/O: 以外存磁盘文件为对象进行输入和输出,即从磁盘文件输入数据,数据输出到磁盘文件。
串I/O : 对内存中指定的空间进行输入和输出。通常指定一个字符数组作为存储空间(实际上可以利用该空间存储任何信息)
2、标准I/O流
标准输入流对象cin,重点掌握的函数
cin.get() //一次只能读取一个字符 遇到EOF结束
cin.get(一个参数) //读一个字符
cin.get(三个参数) //可以读字符串
cin.getline()
标准输出流对象cout
cout.flush()
cout.put()
cout.write()
cout.width()
cout.fill()
cout.setf(标记)
3、文件I/O流
输入输出是以系统指定的标准设备(输入设备为键盘,输出设备为显示器)为对象的。在实际应用中,常以磁盘文件作为对象。即从磁盘文件读取数据,将数据输出到磁盘文件。
和文件有关系的输入输出类主要在fstream.h这个头文件中被定义,在这个头文件中主要被定义了三个类,由这三个类控制对文件的各种输入输出操 作,他们分别是ifstream、ofstream、fstream,其中fstream类是由iostream类派生而来。
由于文件设备并不像显示器屏幕与键盘那样是标准默认设备,所以它在fstream.h头文件中是没有像cout那样预先定义的全局对象,所以我们必须自己定义一个该类的对象。
ifstream类,它是从istream类派生的,用来支持从磁盘文件的输入。
ofstream类,它是从ostream类派生的,用来支持向磁盘文件的输出。
fstream类,它是从iostream类派生的,用来支持对磁盘文件的输入输出。
打开文件
打开文件是指在文件读写之前做必要的准备工作,包括:
1)为文件流对象和指定的磁盘文件建立关联,以便使文件流流向指定的磁盘文件。
2)指定文件的工作方式,如,该文件是作为输入文件还是输出文件,是ASCII文件还是二进制文件等。
以上工作可以通过两种不同的方法实现。