輸入輸出是每一種編程語(yǔ)言必不可少的部分集侯,c++也不例外,下面我們就來(lái)說(shuō)明c++的標(biāo)準(zhǔn)輸入輸出的前世今生乘综。
1.首先說(shuō)一下iostream和iostream.h的區(qū)別
#include<iostream> // 這個(gè)就是1998年標(biāo)準(zhǔn)化以后的標(biāo)準(zhǔn)頭文件,使用時(shí)需要使用聲明命名空間std
#include<iostream.h> // 這個(gè)就是標(biāo)準(zhǔn)化以前的頭文件,里面的函數(shù)以及類(lèi)都是全局的
iostream是現(xiàn)在C++中規(guī)定的標(biāo)準(zhǔn),目的在于使C++代碼用于移植和混合嵌入時(shí)不受擴(kuò)展名.h的限制,避免因?yàn)?h而造成的額外的處理和修改忍饰。
iostream包含的基本功能和對(duì)應(yīng)的iostream.h相同,iostream中定義的內(nèi)容都在命名空間std中棒旗,而iostream.h是為了對(duì)c語(yǔ)言進(jìn)行兼容喘批,所以將標(biāo)準(zhǔn)輸入輸出功能都定義在全局空間中撩荣,他們的使用方法也是不一樣的,另外推薦直接使用iostream饶深,畢竟iostream.h是很多年前的老物件了餐曹,標(biāo)準(zhǔn)c++中已經(jīng)明確不適用了,以后有可能被淘汰敌厘。
注意:在標(biāo)準(zhǔn)化的過(guò)程中台猴,庫(kù)中有些部分的細(xì)節(jié)被修改了,所以舊頭文件和新頭文件中的實(shí)體不一定完全對(duì)應(yīng)
這里看一下他們使用上的不同:
#include<iostream.h>
或者是
#include<iostream>
using namespace std;
可見(jiàn)凡是要使用標(biāo)準(zhǔn)c++輸入輸出俱两,都需要加上using namespace std饱狂。
2.輸入輸出流關(guān)系梳理
要弄清楚c++的輸入輸出流,必須要從源頭找起宪彩,從安裝文件里面找出輸入輸出流相關(guān)的頭文件休讳,大概列一下,相關(guān)頭文件有以下這些:
- istream尿孔,可以看到istream頭文件是聲明了basic_istream模板類(lèi)
- ostream俊柔,ostream頭文件是聲明了basic_ostream模板類(lèi)
- iostream,iostream只是聲明了一個(gè)istream對(duì)象和三個(gè)ostream對(duì)象活合,這一點(diǎn)后面會(huì)說(shuō)明
- iosfwd雏婶,iosfwd頭文件里面聲明了所有輸入輸出類(lèi)的模板類(lèi)的一個(gè)實(shí)例
- fstream,fstream里面聲明了basic_filebuf模板類(lèi)白指、basic_ifstream模板類(lèi)留晚、basic_ofstream模板類(lèi)
- iomainip,iomainip里面聲明了一些帶參數(shù)的操縱算子
- sstream告嘲,sstream里面聲明了basic_stringbuf模板類(lèi)错维、basic_istringstream模板類(lèi)、basic_ostringstream模板類(lèi)
- streambuf橄唬,streambuf里面聲明了basic_streambuf模板類(lèi)
上面說(shuō)到iosfwd對(duì)輸入輸出的類(lèi)模板做了實(shí)例化需五,我們截取一段代碼,如下:
/// Base class for @c char streams.
typedef basic_ios<char> ios; //基礎(chǔ)類(lèi)
/// Base class for @c char buffers.
typedef basic_streambuf<char> streambuf;
/// Base class for @c char input streams.
typedef basic_istream<char> istream;
/// Base class for @c char output streams.
typedef basic_ostream<char> ostream;
/// Base class for @c char mixed input and output streams.
typedef basic_iostream<char> iostream;
/// Class for @c char memory buffers.
typedef basic_stringbuf<char> stringbuf;
/// Class for @c char input memory streams.
typedef basic_istringstream<char> istringstream;
/// Class for @c char output memory streams.
typedef basic_ostringstream<char> ostringstream;
/// Class for @c char mixed input and output memory streams.
typedef basic_stringstream<char> stringstream;
/// Class for @c char file buffers.
typedef basic_filebuf<char> filebuf;
/// Class for @c char input file streams.
typedef basic_ifstream<char> ifstream;
/// Class for @c char output file streams.
typedef basic_ofstream<char> ofstream;
/// Class for @c char mixed input and output file streams.
typedef basic_fstream<char> fstream;
為了敘述方便轧坎,后續(xù)我們直接使用以上實(shí)例類(lèi)來(lái)代指模板類(lèi)宏邮,下面用一張圖說(shuō)明這些類(lèi)之間的關(guān)系:
箭頭代表繼承的關(guān)系,然后相應(yīng)的buf后綴的類(lèi)是同一列的其他類(lèi)使用的緩沖區(qū)類(lèi)缸血。
以istream,ostream,iostream三者為例蜜氨,看一下具體的繼承關(guān)系,如下:
template<typename _CharT, typename _Traits>
class basic_istream : virtual public basic_ios<_CharT, _Traits>;
template<typename _CharT, typename _Traits>
class basic_ostream : virtual public basic_ios<_CharT, _Traits>;
template<typename _CharT, typename _Traits>
class basic_iostream
: public basic_istream<_CharT, _Traits>,
public basic_ostream<_CharT, _Traits>;
可以看到basic_istream和basic_ostream都是虛繼承于basic_ios捎泻,basic_iostream是繼承于basic_istream和basic_ostream飒炎,注意這里繼承于basic_ios的時(shí)候之所以要用虛擬繼承,是為了防止多重繼承時(shí)笆豁,多個(gè)父類(lèi)共用基類(lèi)產(chǎn)生二義性郎汪。
注:所謂二義性是指basic_iostream類(lèi)對(duì)象會(huì)產(chǎn)生兩個(gè)basic_ios對(duì)象赤赊,用了虛繼承后,就只會(huì)產(chǎn)生一個(gè)basic_ios對(duì)象煞赢,從而避免了二義性抛计。
說(shuō)到這里,我想問(wèn)一下照筑,有多少人最開(kāi)始接觸iostream的時(shí)候首先使用的是cin和cout呢吹截,其實(shí)通過(guò)iostream頭文件,我們可以看到凝危,我們常用的cin對(duì)象就是istream的一個(gè)實(shí)例波俄,而cout則是ostream的實(shí)例,標(biāo)準(zhǔn)c++中還聲明了ostream的另外兩個(gè)實(shí)例cerr蛾默、clog懦铺。