14.3.2 流类库层次

    iostream库主要包括如表14.4所示的几个头文件,在前面所有示例代码中使用的头文件<iostream>便是其中之一。

    前面提及的输入输出操作分别是由输入流(istream)和输出流(ostream)这两个类提供的,ios类是istream和ostream类的公共基类,为了允许双向的输入/输出,由istream和ostream派生出了iostream类。

    14.3.2 流类库层次 - 图1

    新旧C++标准中,iostream类库的组织方式稍有不同,不仅体现在头文件是否有后缀上,事实上C++的I/O库被完全改写以适应国际化的需求,旧的C++标准只支持8位char型字符,为了使C++支持各种语言,新的标准扩展了wchar_t字符集。

    旧标准下的I/O库中,诸如iostream等类是确切的定义,其类层次如图14.2所示,其中ios类和streambuf类是类库中的两个基类,其他类均是在此基础上派生而来的,两个类之间没有继承关系,它们是组合使用的,ios类中维护着一个指向streambuf类对象的指针。事实上,ios类仅提供编程界面和格式特征,而streambuf则是做实质性的工作。

    14.3.2 流类库层次 - 图2

    图 14.2 旧标准中I/O库类层次结构略图

    iostream类库中,streambuf、ios、istream、ostream、iostream、istream_withassign和ostream_withassign这些基本I/O流类和预定义的cin、cout、cerr和clog在iostream.h文件(及iostream.h中包含的头文件)中进行说明。filebuf、ifstream、ofstream和fstream在fstream.h中进行说明。strstream、istrstream、ostrstream和strstreambuf在strstream.h中说明。

    注意

    fstream. h和strstrea.h中都包含了iostream.h,所以如果使用标准输入输出(控制台I/O),只要包含iostream.h头文件即可,如果使用fstream或者strstream,只要包含相应的fstream.h和strstrea.h即可。

    每个类的具体作用如表14.5所示。

    14.3.2 流类库层次 - 图3

    新标准中根据wchar_t对I/O库进行了修改,使其模板化,其中包括basic_ios<class T,traits<T>>、basic_istream<class T,traits<T>>等(basic修饰),而原来的ios、istream等只是其在T为char时的实例,如下所示。


    typedef basic_ios<char,char_traits<char>>ios typedef basic_istream<char,char_traits<char>>istream

    其中,traits<T>是一个模板类,为字符类型定义了具体特性,例如,如何比较字符是否相等以及字符的EOF值等,这涉及一些深层次的内容,不是本书讨论的范畴。

    当T为wchar_t时,模板类实例化为wios和wistream形式(w版本),如下所示。


    typedef basic_ios<wchar_t,char_traits<wchar_t>>wios typedef basic_istream<wchar_t,char_traits<wchar_t>>wistream

    抛开实例化来看新标准下的类层次结构,如图14.3所示,其中,斜体加粗、背景为灰色的类为非模板类,其余均为模板类,在诸如basic_iostream类附近的斜体“iostream”是指模板类“basic_iostream”中当T为char时的实例,意思是说,strstream是从iostream派生而来,只对应着char型,没有wchar_t下的strstream版本。

    14.3.2 流类库层次 - 图4

    图 14.3 新标准下的I/O类层次图

    I/O类库中的一些独立于类型的信息被移植到新类ios_base(非模板类)中,包括一些原来在ios中的格式常量,而且,用以初始化的Init类也嵌套在了ios_base中进行定义,访问格式为“ios_base:Init”。

    仍旧可以把basic_ios类和basic_streambuf类看做是类库中的两个基类,其他类均是在此基础上派生而来的,两个类之间没有继承关系,它们是组合使用的,basic_ios类(而不是ios_base类)中维护着一个指向basic_streambuf类对象的指针。

    iostream类库中,streambuf、ios、istream、ostream、iostream这些基本I/O流类的char型特化实现(及其模板类即basic_XXX形式)和预定义的cin、cout、cerr和clog在iostream文件(及iostream中包含的其他头文件)中说明。filebuf、ifstream、ofstream和fstream(及其模板类即basic_XXX形式)在fstream中说明。非模板类strstream、istrstream、ostrstream和strstreambuf在strstream中说明,用以执行C风格的串,也就是字符数组的操作。stringstream、istringstream、ostringstream和stringbuf这些char型特化版本(及其模板类即basic_XXX形式)在头文件<sstream>中实现,用以执行std:string型的操作,关于string的介绍请参考稍后的内容。

    上述如ios等指的是char型实例化后的类,对应的wchar_t版本的类只要在前面加上w即可,如wios和wiostream,如无特别说明,本章所讨论的是char型实例化的情况。

    注意

    <strstream>无法对wchar_t提供有效的支持,其中的内容已经被新的C++标准明确标明为“不要再使用”,推荐使用string版本的<sstream>来替代。

    流可以看做是输入输出类库的对象,<iostream>文件中便预定义了如下4个用于char型操作的流对象。

    ❑cin:标准输入,istream类对象,从标准设备(键盘)中读入数据。

    ❑cout:标准输出,ostream类对象,向标准设备(显示器)输出或者写数据。

    ❑cerr:标准错误输出,ostream类对象,默认情况下,cerr不能重定向,即只能允许向屏幕设备写数据。这个流是没有缓冲区的,意味着信息会自动发送到设备,不会等到缓冲区填满或遇到换行符号。

    ❑clog:标准输出错误,从字面上看有记录的意思,在默认情况下同样不能重定向,只能输出到屏幕上,但这个流有缓冲区。

    新的<iostream>中还定义了流对象wcin、wcout、wcerr和wclog,用以处理wchar_t型信息。

    前面示例中经常使用的cout和cin是对象不是函数,也许这让你有些难以理解。实际上操作符<<和>>就是以友元方式重载在cout和cin类中,以实现内置类型的输入和输出的。举例来说,“cout<<x”相当于执行了“operator<<(cout,x)”。通过对操作符<<和>>重载,就能对自定义的类型进行输入或输出,这就是C++类库的可扩展性。