使用 std::ostream 作为 class 成员

Using std::ostream as a class member

我正在开发一个简单的进度指示器 class,我对使用 std::ostream 对象作为 class 成员有疑问。以下示例在 OS X 和 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() hack。有没有 "better" 更惯用的方法来做到这一点?

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

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

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

protected:
    std::ostream& stream;
    // ...
};