第01讲 运算符重载  

本章主要内容
  运算符重载
  流类库
  文件流

9.1 运算符重载

  C++语言允许程序员重新定义已有的运算符,使其能按用户的要求完成一些特定的操作,这就是所谓的运算符重载。
  运算符重载与函数重载相似,其目的是设置某一运算符,让它具有另一种功能,尽管此运算符在原先C++语言中代表另一种含义,但他们彼此之间并不冲突。C++会根据运算符的位置辨别应使用哪一种功能进行运算。
  C++内部任何运算都是通过函数来实现的。运算符重载的实质就是函数重载。
  在实现过程中,首先把指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型来确定需要调用的函数,这个过程是在编译过程中完成的。
  运算符的重载形式有两种:重载为类的成员函数和重载为类的友元函数。
  运算符重载为类的成员函数的语法形式如下:
  <函数类型> operator <运算符>(<形参表>)
  {
  <函数体>;
  }
  运算符重载为类的友元函数的语法形式如下:
  friend <函数类型> operator <运算符>(<形参表>)
  {
  <函数体>;
  }
  例9.1
  第九章 运算符重载及流类库 - 图1
  第九章 运算符重载及流类库 - 图2
  第九章 运算符重载及流类库 - 图3
  P186 <<、>>和++运算符重载实例
  插入符函数的一般形式为:
  ostream &operator << (ostream & 函数的流, 类名&对象名)
  { …… //函数代码
  return函数的流;
  }
  提取符函数的一般形式为:
  istream &operator >> (istream & 函数的流, 类名&对象名)
  { …… //函数代码
  return函数的流;
  }
  例9.2
  第九章 运算符重载及流类库 - 图4
  第九章 运算符重载及流类库 - 图5
  例9.3
  第九章 运算符重载及流类库 - 图6
  1.函数调用方式;
  2.直接使用运算符
  第九章 运算符重载及流类库 - 图7
  例9.4
  第九章 运算符重载及流类库 - 图8
  第九章 运算符重载及流类库 - 图9
  第九章 运算符重载及流类库 - 图10

第02讲 流类库  

运算符和友元运算符的区别 P190
  如果运算符所需的操作数,尤其是第一个操作数希望进行隐式类型转换,则该运算符应该通过友元来重载。
  另一方面,如果一个运算符的操作需要修改类对象的状态,则应当使用类运算符,这样更符合数据封装的要求。但参数是使用引用还是对象,则要根据运算符在使用中可能出现的情况来决定。
  friend complex operator + (形参1,形参2)
  { ……//函数体定义 }
  关键字friend把 complex operator + (形参1,形参2)说明成类的友元,使得它能够访问类complex 的私有数据。
  形参可以都是对象或者对象的引用;
  形参也可以一个为对象一个为引用,这要视具体问题而定。
  例9.5
  第九章 运算符重载及流类库 - 图11
  例9.6
  第九章 运算符重载及流类库 - 图12

9.2 流类库

9.2.1流类库的基础类

  在C++中,输入输出操作是由“流”来处理的。所谓流,它是C++的一个核心概念,数据从一个位置到另一个位置的流动抽象为流。
  当数据从键盘或磁盘文件流入到程序中时,这样的流称为输入流,把输入数据来自的地方称为“源”
  当数据从程序中流向屏幕或磁盘文件时,这样的流称为输出流,把接收输出数据的地方称为“目标”
  当流被建立后就可以使用一些特定的操作从流中获取数据,如输入操作;也可向流中添加数据,如输出操作。
  从流中获取数据的操作称为提取操作,向流中添加数据的操作称为插入操作。
  执行输入、输出的类体系叫做流类
  提供这个流类实现的系统库叫做流类库
  流类库C++针对流的特点,构造了功能强大的输入输出流库
  第九章 运算符重载及流类库 - 图13
  ios类用来提供一些关于对流状态进行设置的功能,它是一个虚基类,其它类都是从这个派生而来
  但streambuf不是ios类的派生类,在类ios中只是有一个指针成员,指向streambuf类的一个对象。streambuf类是用来为ios类及其派生类提供对数据的缓冲支持。
  缓冲,是指系统在主存中开辟一个专用的区域用来临时存放输入输出信息,这个区域称为缓冲区。有了缓冲以后,输入输出时所占用的CPU时间就大大减少了,提高了系统的效率。因为只有当缓冲区满时,或当前送入的数据为新的一行时,系统才对流中的数据进行处理,称为刷新。
  itream和ostream类均是ios的公有派生类,前者提供了从流中提取数据的有关操作,后者则是提供了向流中插入数据的有关操作。
  iostream类是itream和ostream类公有派生的,该类并没有提供新的操作,只是将itream和ostream类综合在一起,提供一种方便。
  流类库P194
  为了方便用户对基本输入输出流进行操作,只要在程序中包含头文件iostream,就可以使用C++提供的四个预定义的标准流对象:cin、cout、cerr和clog,它们都是std名称空间的流对象。
  cin是istream类的对象,用处理可定向得标准输入,即键盘输入。
  cout是ostream类的对象,用处理标准输出,即屏幕输出。
  cerr和clog都是ostream类的对象,用来处理标准出错信息,并将信息显示在屏幕上。
  在这四个标准流对象中,除了cerr不支持缓冲(发送给它的内容立即被输出到屏幕,并且不能被重定向到其它地方),其余三个都带有缓冲区。
  标准流通常使用提取运算符“>>”和插入运算符“<<”来进行输入输出操作的,而且系统还会自动地完成数据类型的转换。
  一种具体的物理设备,比如说键盘联接起来。
  C++的流类库预定义的4个流所联接起的具体设备为:
  cin 与标准输入设备相联接
  cout 与标准输出设备相联接
  cerr 与标准错误输出设备相联接(非缓冲方式)
  clog 与标准错误输出设备相联接(缓冲方式)

9.2.2默认输入输出格式控制

9.2.3使用ios_base类

  1. ios_base类简介
  ios_base类派生ios类,ios类又是istream类和ostream类的虚基类。
  第九章 运算符重载及流类库 - 图14
  第九章 运算符重载及流类库 - 图15
  2.直接使用格式中控制
  3,使用成员函数

第03讲 文件流  

9.3 文件流

  为方便用户对文件的操作,C++提供了文件操作的文件流库
  第九章 运算符重载及流类库 - 图16
  ifstream类是从istream类公有派生而来,用来支持从输入文件中提取数据的各种操作
  ofstream类是从ostream公有派生而来,用来实现把数据写入到文件中的各种操作。
  fstream类是从iostream类公有派生而来,提供从文件中提取数据或把数据写入到文件的各种操作。
  filebuf类从streambuf类派生而来,用来管理磁盘文件的缓冲区,应用程序中一般很少涉及到该类。
  文件流P199
  C++中文件输入/输出的基本过程
  1.在程序中要包含头文件fstream.h。
  2.创建一个流。
  ifstream iFile;
  ofstream oFile;
  fstream ioFile;
  3.将这个流与文件相关联,即打开文件。
  void open(const char filename,int mode,int access);
  4.文件的读写操作。
  5.关闭文件。
  iFile.close();
  oFile.close();
  参照P201【例9.10】演示重载流运算符的例子
  P197
  【例9.7】演示使用标志位的例子
  第九章 运算符重载及流类库 - 图17
  第九章 运算符重载及流类库 - 图18
  【例9.9】演示文件流的概念
  第九章 运算符重载及流类库 - 图19
  第九章 运算符重载及流类库 - 图20
  第九章 运算符重载及流类库 - 图21
  第九章 运算符重载及流类库 - 图22
  文件流输出流的open函数,即打开文件
  void open(const char
filename,int mode,int filebuf::openprot);

文件打开方式 说 明
Ios_base::in 以输入方式打开文件,即读文件(ifstream类对象默认方式)
Ios_base ::out 以输出方式打开文件,即写文件(ofstream类对象默认方式)
Ios_base ::app 以添加方式打开文件,新增加的内容添加在文件尾
Ios_base ::ate 以添加方式打开文件,新增加的内容添加在文件尾,但下次添加时则添加在当前位置
Ios_base ::trunc 如文件存在就打开并清除其内容,如不存在就建立新文件
Ios_base ::binary 以二进制方式打开文件(默认为文本文件)
Ios_base ::nocreate 打开已有文件,若文件不存在,则打开失败
Ios_base ::noreplace 若打开的文件已经存在,则打开失败

  文件名访问模式打开方式
  文件流filebuf::openport 共享方式,默认的方式
  filebuf::sh_none 独占方式,不允许共享
  filebuf::sh_read 允许读共享
  filebuf::sh_write 允许写共享
  关闭文件时,系统把该文件相关联的文件缓冲区中的数据写到文件中,保证文件的完整,收回与该文件相关的内存空间,可供再分配,把磁盘文件名与文件流对象之间的关联断开,可防止误操作修改了磁盘文件。如又要对文件操作必须重新打开。
  三个文件流类各有一个关闭文件的成员函数 :
  void ifstream::close();
  void ofstream::close();
  void fstream::close();
  使用很方便,如:
  iFile.close();
  oFile.close();
  iofile.close();
  对一个流对象进行输入、输出操作时,可能会产生错误,一般在进行文件的操作时,需要进行相应的错误判断
  if(cin.good())cin>>data;
  表示没有错误和文件没有结束时,才从文件获取数据
  处理错误的成员函数及功能如下:

成员函数 功 能
bad() 如果进行非法操作,返回true,否则返回false
clear() 设置内部错误状态,如果用缺省参量调用则清除所有错误位
eof() 若文件读到末尾,返回true,否则返回false
good() 如果没有错误条件和没有设置文件结束标志,返回true,否则返回false
fail() 与good()相反,操作失败返回false,否则返回true
Is_open() 若流对象是否成功地与文件关联,返回true,否则返回false

  文件存取操作的综合实例
  设计一个student类,用这个类作为数据类型产生一个向量。为简便起见,本例只要求输入学生学号和成绩,将这些信息存入向量中,然后将向量的内容写入文件stud,txt中,最后将向量和文件的内容进行比较,验证存取文件的正确性。
  使用VC设计工程文件student,它含有头文件student.h和源文件student.cpp。
  参照P204~207
  1.头文件student,h
  2.源文件student.cpp
  3.运行示范