我們從一開始就一直在利用C++的輸入輸出在做著各種練習,輸入輸出是由iostream庫提供的,所以討論此標准庫是有必要的,它與C語言的stdio庫不同,它從一開始就是用多重繼承與虛擬繼承實現的面向對象的層次結構,作為一個c++的標准庫組件提供給程序員使用。
iostream為內置類型類型對象提供了輸入輸出支持,同時也支持文件的輸入輸出,類的設計者可以通過對iostream庫的擴展,來支持自定義類型的輸入輸出操作。
為什麼說要擴展才能提供支持呢?我們來一個示例。
由於自定義類的特殊性,在上面的代碼中,無論你使用c風格的輸入輸出,或者是c++的輸入輸出都不是不明確的一個表示,由於c語言沒有運算符重載機制,導致stdio庫的不可擴充性,讓我們無法讓printf()和scanf()支持對自定義類對象的擴充識別,而c++是可以通過運算符重載機制擴充iostream庫的,使系統能能夠識別自定義類型,從而讓輸入輸出明確的知道他們該干什麼,格式是什麼。
在上例中我們之所以用printf與cout進行對比目的是為了告訴大家,C與C++處理輸入輸出的根本不同,我們從c遠的輸入輸出可以很明顯看出是函數調用方式,而c++的則是對象模式,cout和cin是ostream類和istream類的對象。
C++中的iostream庫主要包含下圖所示的幾個頭文件:
我們所熟悉的輸入輸出操作分別是由istream(輸入流)和ostream(輸出流)這兩個類提供的,為了允許雙向的輸入/輸出,由istream和ostream派生出了iostream類。
類的繼承關系見下圖:
iostream庫定義了以下三個標准流對象:
1.cin,表示標准輸入(standard input)的istream類對象。cin使我們可以從設備讀如數據。
2.cout,表示標准輸出(standard output)的ostream類對象。cout使我們可以向設備輸出或者寫數據。
3.cerr,表示標准錯誤(standard error)的osttream類對象。cerr是導出程序錯誤消息的地方,它只能允許向屏幕設備寫數據。
輸出主要由重載的左移操作符(<<)來完成,輸入主要由重載的右移操作符(>>)完成。
>>a表示將數據放入a對象中。
<
這些標准的流對象都有默認的所對應的設備,見下表:
圖中的意思表明cin對象的默認輸入設備是鍵盤,cout對象的默認輸出設備是顯示器屏幕。
那麼原理上C++有是如何利用cin/cout對象與左移和右移運算符重載來實現輸入輸出的呢?
下面我們以輸出為例,說明其實現原理:
cout是ostream類的對象,因為它所指向的是標准設備(顯示器屏幕),所以它在iostream頭文件中作為全局對象進行定義。
ostream cout(stdout);//其默認指向的C中的標准設備名,作為其構造函數的參數使用。
在iostream.h頭文件中,ostream類對應每個基本數據類型都有其友元函數對左移操作符進行了友元函數的重載。
ostream& operator<<(ostream &temp,int source);
ostream& operator<<(ostream &temp,char *ps);
。。。。等等
一句輸出語句:cout<<"www.cndev-lab.com";,事實上調用的就是ostream& operator<<(ostream &temp,char *ps);這個運算符重載函數,由於返回的是流對象的引用,引用可以作為左值使用,所以當程序中有類似cout<<"www.cndev-lab.com"<<"中國軟件開發實驗室";這樣的語句出現的時候,就能夠構成連續輸出。
由於iostream庫不光支持對象的輸入輸出,同時也支持文件流的輸入輸出,所以在詳細講解左移與右移運算符重載只前,我們有必要先對文件的輸入輸出以及輸入輸出的控制符有所了解。
和文件有關系的輸入輸出類主要在fstream.h這個頭文件中被定義,在這個頭文件中主要被定義了三個類,由這三個類控制對文件的各種輸入輸出操作,他們分別是ifstream、ofstream、fstream,其中fstream類是由iostream類派生而來,他們之間的繼承關系見下圖所示。
由於文件設備並不像顯示器屏幕與鍵盤那樣是標准默認設備,所以它在fstream.h頭文件中是沒有像cout那樣預先定義的全局對象,所以我們必須自己定義一個該類的對象,我們要以文件作為設備向文件輸出信息(也就是向文件寫數據),那麼就應該使用ofstream類。
ofstream類的默認構造函數原形為:
ofstream::ofstream(const char *filename,int mode = ios::out,int openprot = filebuf::openprot);
filename: 要打開的文件名
mode: 要打開文件的方式
prot: 打開文件的屬性
其中mode和openprot這兩個參數的可選項表見下表:
mode屬性表
ios::app: 以追加的方式打開文件
ios::ate: 文件打開後定位到文件尾,ios:app就包含有此屬性
ios::binary: 以二進制方式打開文件,缺省的方式是文本方式。兩種方式的區別見前文
ios::in: 文件以輸入方式打開
ios::out: 文件以輸出方式打開
ios::trunc: 如果文件存在,把文件長度設為0
可以用“或”把以上屬性連接起來,如ios::out|ios::binary。
openprot屬性表:
0:普通文件,打開訪問
1:只讀文件
2:隱含文件
4:系統文件
可以用“或”或者“+”把以上屬性連接起來 ,如3或1|2就是以只讀和隱含屬性打開文件。
示例代碼如下: