继承自std :: basic_streambuf以写入套接字

Vir*_*721 10 c++ inheritance iostream stream streambuf

我想编写一个我自己的日志库,它为日志条目的发送位置提供抽象.

C++的IO库已经用std::stringstream和提供了那种抽象std::fstream.我也希望能够从/向套接字读/写.

我读到扩展标准库的正确方法是继承std::basic_streambuf.我不明白的是,如果继承std::basic_streambufstd::basic_filebuf呢,哪里是需要的std::ifsream,std::ofstreamstd::fstream班?我不能只用一个子类的实例替换某些流的缓冲区,该子类的std::basic_streambuf输出输出到我想要的地方吗?

到目前为止,我已经完成了以下工作,但我真的不确定我在做什么.以下设计是否正确?

template< typename char_type, typename traits_type = std::char_traits< char_type > >
class basic_sock_streambuf : public std::basic_streambuf< char_type, traits_type >
{
public:

    basic_sock_streambuf()
    {

    }

    ~basic_sock_streambuf()
    {

    }

    int overflow (int c = EOF)
    {
        fputc( c, stdout ); // Temporary.
        return traits_type::to_int_type( c );
    }

    int underflow()
    {
        return fgetc( stdout ); // Temporary.
    }

    int sync()
    {
        return 0;
    }
};

template< typename char_type, typename traits_type = std::char_traits< char_type > >
class basic_isockstream : public std::basic_istream< char_type, traits_type >
{
};

template< typename char_type, typename traits_type = std::char_traits< char_type > >
class basic_osockstream : public std::basic_ostream< char_type, traits_type >
{
};

template< typename char_type, typename traits_type = std::char_traits< char_type > >
class basic_socktream : public basic_isockstream< char_type, traits_type >, public basic_osockstream< char_type, traits_type >
{
private:

    typedef basic_isockstream< char_type, traits_type > iparent;

    typedef basic_osockstream< char_type, traits_type > oparent;

    basic_sock_streambuf< char_type, traits_type > sock_sb;

    std::basic_streambuf< char_type, traits_type > * old_isb;

    std::basic_streambuf< char_type, traits_type > * old_osb;

public:

    basic_socktream()
    {
        old_isb = iparent::rdbuf( & sock_sb );
        old_osb = oparent::rdbuf( & sock_sb );
    }

    ~basic_socktream() throw()
    {
        iparent::rdbuf( old_isb );
        oparent::rdbuf( old_osb );
    }
};
Run Code Online (Sandbox Code Playgroud)

编辑:根据答案更新代码:

template<
    typename char_type,
    typename traits_type = std::char_traits< char_type > >
class basic_sockbuf :
    public std::basic_streambuf< char_type, traits_type >
{
public:

    basic_sockbuf()
    {
    }

    ~basic_sockbuf()
    {
    }

    int overflow( int c = EOF )
    {
        fputc( c, stdout ); // Temporary.
        return traits_type::to_int_type( c );
    }

    int underflow()
    {
        return fgetc( stdout ); // Temporary.
    }

    int sync()
    {
        return 0;
    }
};

template<
    typename char_type,
    typename traits_type = std::char_traits< char_type > >
class basic_isockstream :
    public std::basic_istream< char_type, traits_type >
{
private:

    typedef std::basic_istream< char_type, traits_type > parent;

    basic_sockbuf< char_type, traits_type > buffer;

public:

    basic_isockstream() :
        std::basic_istream< char_type, traits_type >::basic_istream(),
        buffer()
    {
        init( & buffer );
    }
};

template<
    typename char_type,
    typename traits_type = std::char_traits< char_type > >
class basic_osockstream :
    public std::basic_ostream< char_type, traits_type >
{
private:

    basic_sockbuf< char_type, traits_type > buffer;

public:

    basic_osockstream() :
        std::basic_ostream< char_type, traits_type >::basic_istream(),
        buffer()
    {
        init( & buffer );
    }
};

template<
    typename char_type,
    typename traits_type = std::char_traits< char_type > >
class basic_socktream :
    public std::basic_iostream< char_type, traits_type >,
    public basic_sockbuf< char_type, traits_type >
{
private:

    basic_sockbuf< char_type, traits_type > buffer;

public:

    basic_socktream() :
        std::basic_iostream< char_type, traits_type >::basic_iostream(),
        buffer()
    {
        std::basic_iostream< char_type, traits_type >::init( & buffer );
    }
};
Run Code Online (Sandbox Code Playgroud)

Sam*_*hik 6

std::istreamstd::ostream提供格式化的输入和输出操作。也就是说,将流转换为/从数字、字符串等...

std::basic_streambuf是一个较低级别的接口,用于从...某处读取或写入字符块。这就是您需要子类化和实现的内容。

而且,您走在正确的轨道上。二者std::istreamstd::ostream具有一个重载构造函数,一个指针指向一个流缓冲器。所以,你的行动计划是:

  1. 子类化并实现您的自定义std::basic_streambuf.

  2. 使用指向流缓冲区的指针构造 astd::istream或 a std::ostream

我不能用 std::basic_streambuf 的子类的实例替换某个流的缓冲区吗

不,不是替换,而是构建一个。您使用指向缓冲区的指针构造 astd::istream或 a std::ostream。您不会使用 a std::[io]fstream,而是使用std::istreamand std::ostream,使用您的流缓冲区构造。

所有一个std::ifstream是,例如,是的一个子类std::istream的是构造其超类的指针的内部流缓冲器从文件中读取。

随意创建您自己的 的子类std::istream,它从您的流缓冲区子类乘法继承,并且std::istream首先构造流缓冲区子类,然后是std::istream.