2012-08-06 30 views
0

我使用STLPort的5.2.1,我想用一个自定义std::filebuf实现有Visual Studio 2008的C++应用程序03。例如:如何覆盖std :: filebuf?

class MyFileBuf : public std::filebuf 
{ 
protected: 
    virtual int_type sync() 
    { 
     // breakpoint here never fires 
     return std::filebuf::sync(); 
    }; 

    virtual std::streamsize xsputn(const char_type* p, std::streamsize n) 
    { 
     // breakpoint here never fires 
     return std::filebuf::xsputn(p, n); 
    }; 

    virtual int_type overflow(int_type c = traits_type::eof()) 
    { 
     // breakpoint here never fires 
     return std::filebuf::overflow(c); 
    }; 
}; 

class MyFileStream : public std::ofstream 
{ 
public: 
    MyFileStream() : std::ofstream(new MyFileBuf()) { clear(); }; 
    ~MyFileStream() { delete rdbuf(); }; 
}; 

int main() 
{ 
    MyFileStream fs; 
    fs.open("test.txt"); 
    fs << "this is a test" << std::endl; 
    return 0; 
} 

不幸的是,MyFileBuf的成员都没有被调用过。如果我通过代码,我看到<<运营商进入

stlpd_std::basic_streambuf<char,stlpd_std::char_traits<char> >::xsputn(const char* __s, long int __n) 
stlpd_std::basic_streambuf<char,stlpd_std::char_traits<char> >::sputn(const char* __s, long int __n) 
stlpd_std::basic_ostream<char,stlpd_std::char_traits<char> >::_M_put_nowiden(const char* __s) 
stlpd_std::operator<<<stlpd_std::char_traits<char> >(stlpd_std::basic_ostream<char,stlpd_std::char_traits<char> >& , const char* __s) 
main() 

在那里我会想到调用堆栈的顶部是:

MyFileBuf::xsputn(const char* p, long int n) 

的文件,但是,正确书写。任何人都可以帮助我理解我要出错的地方吗?

+1

我很惊讶,编译。 'ofstream'没有一个带'streambuf *'参数的构造函数。我可以看到没有理由从'ofstream'派生'MyFileStream',只是'ostream'没问题。无法真正看到从'filebuf'派生'MyFileBuf'的原因,'streambuf'也是正常的。也许如果你解释你为什么试图这样做会有帮助。 – jahhaj 2012-08-06 21:59:04

+1

事实上,'流'不能这样构建。有些STL库提供的“扩展”最终会在最不经意的时候回到你身边,就像在这种情况下一样。在这种情况下,在构造函数内调用'init(new MyFileBuf)'应该正确执行初始化。 – DanielKO 2012-08-06 22:52:55

+0

@DanielKO - 你说得对。我无意中使用STLPort扩展。当我把它关闭时,我得到了jahhaj预测的编译错误。 – PaulH 2012-08-07 13:56:50

回答

0

感谢@jahhaj和@DanielKO对你有所帮助。

的解决问题的方法是这样的:

#include <iostream> 
#include <fstream> 
using namespace std; 

class MyFileBuf : public std::filebuf 
{ 
protected: 
    virtual int_type sync() 
    { 
     return std::filebuf::sync(); 
    }; 

    virtual std::streamsize xsputn(const char_type* p, std::streamsize n) 
    { 
     return std::filebuf::xsputn(p, n); 
    }; 

    virtual int_type overflow(int_type c = traits_type::eof()) 
    { 
     return std::filebuf::overflow(c); 
    }; 
}; 

class MyFileStream : public std::ostream 
{ 
public: 
    MyFileStream() : std::ostream(0) { init(&buf_); }; 
    MyFileStream(const char* filename, std::ios_base::openmode mode = std::ios_base::out) 
     : std::ostream(0) 
    { 
     init(&buf_); 
     this->open(filename, mode); 
    } 

    bool is_open() const { return buf_.is_open(); }; 

    void close() { buf_.close(); }; 

    void open(const char* filename, std::ios_base::openmode mode = std::ios_base::out) 
    { 
     buf_.open(filename, mode); 
    }; 

    std::filebuf* rdbuf() { return &buf_; }; 

private: 
    MyFileBuf buf_; 
}; 

int main() 
{ 
    MyFileStream fs("test.txt"); 
    fs << "this is a test" << std::endl; 
    return 0; 
} 

Example