在C++有一個名稱manipulator(操控器),是專門用來操空stream的物件,只會改變輸入或格式化輸出的解釋方式。
用於ostream的操控器並不會憑空造出輸出資料,有些操控器會引發立即的動作,如果「刷新(flush)output緩衝區」
或「輸出換行符號'\n'」,等等的動作。在學習C++中對於endl、flush並不會陌生,接下來要說明他們到底是什麼樣
子呢?在標題檔ostream中,可以查到下列的程式:
// MANIPULATORS
template<class _E, class _Tr> inline
basic_ostream<_E, _Tr>&
__cdecl endl(basic_ostream<_E, _Tr>& _O)
{_O.put(_O.widen('\n'));
_O.flush();
return (_O); }
_CRTIMP inline basic_ostream<char, char_traits<char> >&
__cdecl endl(basic_ostream<char, char_traits<char> >& _O)
{_O.put('\n');
_O.flush();
return (_O); }
_CRTIMP inline basic_ostream<wchar_t, char_traits<wchar_t> >&
__cdecl endl(basic_ostream<wchar_t,
char_traits<wchar_t> >& _O)
{_O.put('\n');
_O.flush();
return (_O); }
return (_O); }
template<class _E, class _Tr> inline
basic_ostream<_E, _Tr>&
__cdecl flush(basic_ostream<_E, _Tr>& _O)
{_O.flush();
return (_O); }
_CRTIMP inline basic_ostream<char, char_traits<char> >&
__cdecl flush(basic_ostream<char, char_traits<char> >& _O)
{_O.flush();
return (_O); }
_CRTIMP inline basic_ostream<wchar_t, char_traits<wchar_t> >&
__cdecl flush(basic_ostream<wchar_t,
char_traits<wchar_t> >& _O)
{_O.flush();
return (_O); }
綠色字體請參考前一篇文章,而且以下的程式將省略以上綠色字體。
在此說明widen(...),flush(),put(char c):
widen(char c):用來將一個原生(native)字元集內「型別為char」的字元,轉換為「locale所用字元集」
內對應字元。也就是說此函式來「拓寬」一個字元,即使結果亦為char型別也無妨。若與國際化議題無關時
可以不需在意。主要的目是在於國際化的議題。
flush():刷新output stream的緩衝區,將緩衝區的內容寫至輸出裝置中(如螢幕)
put(char c):將引數c寫至stream,傳回stream。
template<class _E, class _Tr> inline basic_ostream<_E, _Tr>& ???(basic_ostream<_E, _Tr>& _O)
inline basic_ostream<char, char_traits<char> >& ???(basic_ostream<char, char_traits<char> >& _O)
inline basic_ostream<wchar_t, char_traits<wchar_t> >& ???(basic_ostream<wchar_t, char_traits<wchar_t> >& _O)
不管是endl或flush都會有一個template的版本、char特化版本及wchar_t特化版本,但其實若不理國際化的議題時
,char特化版本已經夠用,所以接下來只討論char特化的版本。所以現在簡化為:
inline basic_ostream<char, char_traits<char> >& endl(basic_ostream<char, char_traits<char> >& _O)
{ _O.put('\n'); _O.flush(); return (_O); }
inline basic_ostream<char, char_traits<char> >& flush(basic_ostream<char, char_traits<char> >& _O)
{ _O.flush(); return (_O); }
在前一篇文章中提到basic_ostream<char, char_traits<char> >與ostream是一樣的,所以上式可變為:
inline ostream& endl(ostream& _O)
{ _O.put('\n'); _O.flush(); return (_O); }
inline ostream& flush(ostream& _O)
{ _O.flush(); return (_O); }
那清楚endl與flush是什麼嗎?是一個函式,函式具有一個參數,型態為ostream&,而回傳值ostream&。
而當在operator<<中使用endl或flush時,會呼叫那一類型的operator<<呢?以下:
ostream& operator<<(ostream& (__cdecl *_F)(ostream&))
{return ((*_F)(*this)); }
_F是一個函式指標,指向函式,函式具有一個型態ostream&的參數及回傳值型態為ostream&。endl與flush正是
這一類的函式。假設程式為:cout<<endl; 這個程式同等為:cout.operator<<(endl); 所以對照上式的型式,可
得_F指向endl,並利用函式指標,執行endl的動作。flush的動同亦是一樣。
Written By James On 2004/02/08