4
我想通過擴展std::streambuf
來了解更多關於C++ I/O流庫的工作原理。作爲一個學習實驗,我的目標是簡單地創建一個自定義流,將所有輸出指向std::cerr
。它似乎很簡單:擴展C++ ostream
#include <iostream>
using namespace std;
class my_ostreambuf : public std::streambuf
{
public:
protected:
std::streamsize xsputn(const char * s, std::streamsize n)
{
std::cerr << "Redirecting to cerr: " << s << std::endl;
return n;
}
};
int main()
{
my_ostreambuf buf;
std::ostream os(&buf);
os << "TEST";
}
這似乎工作,因爲它打印Redirecting to cerr: TEST
。問題是它不起作用當一個單個字符(而不是一個字符串)通過std::ostream::sputc
插入到流中時。例如:
int main()
{
my_ostreambuf buf;
std::ostream os(&buf);
os << "ABC"; // works
std::string s("TEST");
std::copy(s.begin(), s.end(), std::ostreambuf_iterator<char>(os)); // DOESN'T WORK
}
我想這個問題是xsputn
不處理單個字符插入。 (我猜sputc
內部不會調用xsputn
?)但是,看看list of virtual protected functionsstd::streambuf
,我沒有看到任何我應該重寫的函數處理單個字符插入。
那麼,我該如何做到這一點?
那麼,什麼是處理'sputc'? – 0x499602D2
@ 0x499602D2:'sputc'將一個字符寫入由streambuf維護的內部緩衝區。當緩衝區滿或者使用'endl'或'flush'操縱器時(以及其他一些情況),這個緩衝區會被刷新。當緩衝區被刷新時,如果下一個字符沒有被填滿,下一個字符將被調用'overflow'(或者如果緩衝區未滿時被刷新,則使用'eof')。這個想法是'overflow'將緩衝區的內容,以及作爲參數傳遞的字符(如果不是'eof')寫入實際的目的地。 (在下一條評論中繼續) – HighCommander4
@ 0x499602D2:因此,可以通過覆蓋「overflow」來編寫一個正常運行的streambuf實現。一次輸出一串字符時使用'xsputn'。它的默認實現只是將每個字符寫入內部緩衝區,就像通過'sputc'(最終它們將被「overflow」處理)一樣。然而,'xsputn'可以被覆蓋,做一些更有效的操作,例如繞過緩衝區並直接將字符串寫入目的地。 – HighCommander4