#include usingnamespacestd; intmain() {
cout<<"Hello,World!"<return0; }
由于以前學過C,所以這段代碼的其它部分在我看來都還算“正?!保欢鴆out卻很獨特:既不是函數,似乎也不是C++非凡規定出來的像if,for一類有非凡語法的“語句”。由于只是初步介紹,所以那本書只是簡單的說cout是C++中的“標準輸入輸出流”對象……這于我而言實在是一個很深奧的術語。這還沒完,之后又遇見了cin……因為不知底細,從此使用它們的時候都誠惶誠恐,幾欲逃回C時代那簡明的PRintf(),究竟好歹我可以說:我在調用的是一個函數。那有著一長串<<、>>的玩意,究竟算怎么回事呢?我一直想把它們當作要害字,可偏偏不是,而且居然是用C++語言“做”出來的,呵!但printf()用多了就開始有人好心地批判我的程序“C語言痕跡過重”…… 后來隨著學習的深入,總算大概明白了cout/cin/cerr/...的鬼把戲:那些東東不過是變著法兒“哄人”,其實說到底還是函數調用,不過這函數有些非凡,用的是運算符重載,確切地說(以下還是以cout為例)是重載了“<<”運算符。我們現在就讓它現出函數的本來面目,請看HelloWorld!的等效版本: #include usingnamespacestd; intmain() { cout.Operator<<("Hello,World!"); cout.operator<<(endl); return0; }
編譯運行,結果與經典版無二。上面程序應該更輕易理解了:cout是一個iostream類的對象,它有一個成員運算符函數operator<<,每次調用的時候就會向輸出設備(一般就是屏幕啦)輸出東東。嗯,這里有一個問題:為什么函數operator<<能夠接受不同類型的數據,如整型、浮點型、字符串甚至指針,等等呢? 我想你現在已經猜到了,沒錯,就是用運算符重載。運算符函數與一般函數基本無異,可以任意重載。標準庫的設計者們早已經為我們定制了iostream::operator<<對于各種C++基本數據類型的重載版本,這才使得我們這些初學者們一上來就享受到cout<<"Hello,World!"<classMyOutstream {
public: constMyOutstream&operator<<(intvalue)const;//對整型變量的重載 constMyOutstream&operator<<(char*str)const;//對字符串型的重載 }; constMyOutstream&MyOutstream::operator<<(intvalue)const { printf("%d",value); return*this;//注重這個返回…… } constMyOutstream&MyOutstream::operator<<(char*str)const { printf("%s",str); return*this;//同樣,這里也留意一下…… } MyOutstreammyout;//隨時隨地為我們服務的全局對象myout intmain() { inta=2003; char*myStr="Hello,World!"; myout<我們已經的myout已經初具形態,可以為我們工作了。程序中的注釋指出兩處要我們非凡注重的:即是operator<<函數執行完畢之后,總是返回一個它本身的引用,輸出已經完成,為何還要多此一舉? 還記得那個有點奇異的cout.operator<<("Hello,World!").operator<<(endl)么?它能實現意味著我們可以連著書寫 cout<<"Hello,World!"<而不是 cout<<"Hello,World!"; cout<為何它可以這樣連起來寫?我們分析一下:按執行順序,系統首先調用cout.operator<<("Hello,World!"),然后呢?然后cout.operator<<會返回它本身,就是說在函數的最后一行會出現類似于return*this這樣的語句,因此cout.operator<<("Hello,World!")的調用結果就返回了cout,接著它后面又緊跟著.operator<<(endl),這相當于cout.operator<<(endl)——于是又會進行下一個輸出,假如往下還有很多<<算符,調用就會一直進行……哇噢,是不是很聰明?現在你明白我們的MyOutstream::operator<<最后一行的奧妙了吧! 再注重一下main函數中最激動人心的那一行: myout<ipulator),它不但實現了換行操作,而且還對輸出緩沖區進行刷新。什么意思呢?原來在執行輸出操作之后,數據并非馬上傳到輸出設備,而是先進入一個緩沖區,當適宜的時機(如設備空閑)后再由緩沖區傳入,也可以通過操縱符flush進行強制刷新: cout<<"Hello,World!"<<"Flushthescreennow!!!"<這樣當程序執行到operator<<(Flash)之前,有可能前面的字符串數據還在緩沖區中而不是顯示在屏幕上,但執行operator<<(flash)之后,程序會強制把緩沖區的數據全部搬運到輸出設備并將其清空。而操縱符endl相當于<<"/n"<不過可能在屏幕上顯示是手動刷新與否區別看來都不大。但對于文件等輸出對象就不大一樣了:過于頻繁的刷新意味著老是寫盤,會影響速度。因此通常是寫入一定的字節數后再刷新,如何操作?靠的就是這些操縱符。
好了,說了這么多,C++的iostream家族與C的print/scanf家庭相比究竟有何優勢?首先是類型處理更安全、智能,想想printf中對付int、float等的"%d"、"%f"等說明符真是多余且麻煩,萬一用錯了搞不好還會死掉;其次是擴展性更強:我要是新定義一個復數類Complex,printf對其是無能為力,最多只能分別輸出實、虛部,而iostream使用的<<、>>操作符都是可重載的,你只要重載相關的運算符就可以了;而且流風格的寫法也比較自然簡潔,不是么?
更多內容請看C/C++技術學堂專題,或
新聞熱點
疑難解答