How to inherit from std::ostream?

I was spinning my head around how to do the same thing and i found out it's actually not that hard. Basically just subclass the ostream and the streambuf objects, and construct the ostream with itself as the buffer. the virtual overflow() from std::streambuf will be called for every character sent to the stream. To fit your example i just made a foo() function and called it.

#include <iostream>

struct Bar :  private std::streambuf , public std::ostream
{
    Bar() : std::ostream(this) {}

private:
    int overflow(int c) override
    {
        foo(c);
        return 0;
    }


    void foo(char c)
    {
        std::cout.put(c);

    }
};

int main()
{
    Bar b;
    b<<"Look a number: "<<std::hex<<29<<std::endl;

    return 0;
}

EDIT: The old code used the wrong initialization order. Although it had no visible side effects, the streambuf object should be initialized before passing it to the ostream object. Since C++ initializes parents left to right, I moved std::streambuf to the left to make the code correct.

EDIT: I changed the code to inherit std::streambuf privately to keep the interface cleaner and keep the class encapsulated.


It's not a simple question, unfortunately. The classes you should derive from are the basic_ classes, such as basic_ostream. However, derivation from a stream may not be what you want, you may want to derive from a stream buffer instead, and then use this class to instantiate an existing stream class.

The whole area is complex, but there is an excellent book about it Standard C++ IOStreams and Locales, which I suggest you take a look at before going any further.


Another working hack to achieve a similar effect is to use template and composition

class LoggedStream {
public:
  LoggedStream(ostream& _out):out(_out){}
  template<typename T>
  const LoggedStream& operator<<(const T& v) const {log();out << v;return *this;}
protected:
  virtual void log() = 0;
  ostream& out;
};

class Logger : LoggedStream {
  void log() { std::cerr << "Printing" << std::endl;}
};

int main(int,char**) {LoggedStream(std::cout) << "log" << "Three" << "times";}