繁体   English   中英

C++ 装饰 basic_iostream 类

[英]C++ Decorate basic_iostream classes

我想做如下代码所示的操作:

class foo
{
private:
    std::fstream* m_stream;

public:
    foo(std::fstream* stream) : m_stream(stream) { }

    foo& write(char const* s, std::streamsize count)
    {
        if (/*condition*/)
        {
            m_stream->write(s, count);
        }
        else
        {
            // ...
        }

        return *this;
    }

    foo& read(char* s, std::streamsize count)
    {
        if (/*condition*/)
        {
            m_stream->read(s, count);
        }
        else
        {
            // ...
        }

        return *this;
    }
};

我需要向所有类似的方法(例如put )添加相同的行为。 这不应仅应用于文件流,而是所有其他流类。 有没有简单的方法来允许这些功能?

许多格式化输出运算符 ( operator<< ) 直接写入底层流缓冲区。 为了以一般方式完成此操作,您需要做的是从 std::basic_streambuf 派生一个类,该类将所有数据转发到另一个 std::basic_streambuf,然后可选地创建一个最小的 std::basic_ostream 实现以使用您的流缓冲更容易。

不过,我不会说这特别容易,但这是以可能影响所有流类型的方式执行此操作的唯一方法。

这是转发到另一个流缓冲区的最小流缓冲区的示例(并执行一些无意义的转换只是为了演示您可以做什么),以及一个伴随的流:

#include <iostream>
#include <streambuf>

template<typename CharType, typename Traits = std::char_traits<CharType> >
class ForwardingStreamBuf : public std::basic_streambuf<CharType, Traits>
{
public:
    typedef Traits traits_type;
    typedef typename traits_type::int_type int_type;
    typedef typename traits_type::pos_type pos_type;
    typedef typename traits_type::off_type off_type;

    ForwardingStreamBuf(std::basic_streambuf<CharType, Traits> *baseStreamBuf)
        : _baseStreamBuf(baseStreamBuf)
    {
    }

protected:
    virtual int_type overflow(int_type c = traits_type::eof())
    {
        if( _baseStreamBuf == NULL )
            return traits_type::eof();

        if( traits_type::eq_int_type(c, traits_type::eof()) )
            return traits_type::not_eof(c);
        else
        {
            CharType ch = traits_type::to_char_type(c);
            if( ch >= 'A' && ch <= 'z' )
                ch++; // Do some meaningless transformation
            return _baseStreamBuf->sputc(ch);
        }
    }

    virtual int sync()
    {
        if( _baseStreamBuf == NULL )
            return -1;
        else
            return _baseStreamBuf->pubsync();
    }
private:
    std::basic_streambuf<CharType, Traits> *_baseStreamBuf;
};

template<typename CharType, typename Traits = std::char_traits<CharType> >
class ForwardingStream : public std::basic_ostream<CharType, Traits>
{
public:
    ForwardingStream(std::basic_ostream<CharType, Traits> &stream)
        : std::basic_ostream<CharType, Traits>(NULL), _buffer(stream.rdbuf())
    {
        this->init(&_buffer);
    }

    ForwardingStreamBuf<CharType, Traits>* rdbuf() const
    {
        return &_buffer;
    }
private:
    ForwardingStreamBuf<CharType, Traits> _buffer;
};

这可以非常简单地使用:

int main()
{
    ForwardingStream<char> test(std::cout);
    test << "Foo" << std::endl;
}

这将输出Gpp 我希望这对你有所帮助。

像这样的东西?

   template <class Stream>
    class DecoratedStream {
    public:
      DecoratedStream(Stream* stream) : m_stream(stream) {}

      DecoratedStream& write(const char* data, int count) {
        m_stream->write(data, count);
      }

    };

如果我理解正确,您想装饰任何iostream方法。 因此,只需让您的装饰器将iostream作为装饰对象(而不是fstream ,它是iostream的子类)。

将指针放在结构内作为您当前的方法是危险且容易出错的。 相反,只需派生此类stream类并实现基本构造函数并环绕您的自定义方法,例如write()

template<typename StreamType>
class foo : StreamType
{
  // wrapper constructors supporting StreamType() constructors
  foo& write(char const* s, std::streamsize count)
  {
    //...
    return *this;
  }
};

用法:

foo<fstream> obj;
obj.write(...);

此类问题的常用解决方案是使用模板。 std::istreamstd::ostream which need covering, and a good template member for函数并不多std::ostream which need covering, and a good template member for << and >> std::ostream which need covering, and a good template member for should cover a lot of the cases. In most of the cases I've done this, I've only offerred should cover a lot of the cases. In most of the cases I've done this, I've only offerred << or >>`。 (一般来说,我不需要双向流。)

至于处理其他类型的流,只需使用std::iostream而不是std::fstream (通常,除了打开文件时,您不应该看到fstream部分。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM