使用std::ostream作为类成员

Using std::ostream as a class member

本文关键字:成员 ostream std 使用      更新时间:2023-10-16

我正在处理一个简单的进度指示器类,我有一个关于使用std::ostream对象作为类成员的问题。以下示例在OSX和Linux上正确编译和运行。

#include <iostream>
#include <string>
struct ProgressIndicator {
public:
    ProgressIndicator(unsigned int update_interval, std::string message,
                      std::ostream& outstream = std::cerr)
        : update_interval(update_interval), message(message),
          stream(outstream.rdbuf()), _counter(0), _interval(update_interval)
    {
    }
    void increment(unsigned int by = 1)
    {
        _counter += by;
        if(_counter >= _interval) {
            stream << message << _counter << std::endl;
            _interval += update_interval;
        }
    }
    unsigned int get_count()
    {
        return _counter;
    }
protected:
    unsigned int update_interval;
    std::string message;
    std::ostream stream;
private:
    unsigned long _counter;
    unsigned long _interval;
};
int main()
{
    ProgressIndicator p1(5, "progress <stdout> ", std::cout);
    for(int i = 0; i < 15; i++) {
        p1.increment();
    }
    ProgressIndicator p2(5, "progress <stderr> ", std::cerr);
    for(int i = 0; i < 15; i++) {
        p2.increment();
    }
    return 0;
}

我知道std::ostream对象不能复制,必须通过引用传递。但我不明白为什么用stream(outstream)初始化不起作用,以及为什么我不得不求助于rdbuf()破解。没有比这更好、更地道的方法吗?

您仍在复制std::ostream。即使构造函数没有复制参数,它仍然需要以某种方式将对象复制到ProgressIndicator::stream中。

解决问题的一种方法是存储对流的引用,尽管只有当你知道流对象将比你的类实例更持久时,这才有效:

struct ProgressIndicator {
    ProgressIndicator(std::ostream& outstream = std::cerr /* ... */)
      : stream(outstream) /* ... */ {}
    // ...
protected:
    std::ostream& stream;
    // ...
};