How to override cout in C++?
Solution 1
Overriding the behaviour of std::cout
is a really bad idea as other developers will have a hard time understanding that the use of std::cout
doesn't behave as usual.
Make your intention clear with a simple class
#include <fstream>
#include <iostream>
class DualStream
{
std::ofstream file_stream;
bool valid_state;
public:
DualStream(const char* filename) // the ofstream needs a path
:
file_stream(filename), // open the file stream
valid_state(file_stream) // set the state of the DualStream according to the state of the ofstream
{
}
explicit operator bool() const
{
return valid_state;
}
template <typename T>
DualStream& operator<<(T&& t) // provide a generic operator<<
{
if ( !valid_state ) // if it previously was in a bad state, don't try anything
{
return *this;
}
if ( !(std::cout << t) ) // to console!
{
valid_state = false;
return *this;
}
if ( !(file_stream << t) ) // to file!
{
valid_state = false;
return *this;
}
return *this;
}
};
// let's test it:
int main()
{
DualStream ds("testfile");
if ( (ds << 1 << "\n" << 2 << "\n") )
{
std::cerr << "all went fine\n";
}
else
{
std::cerr << "bad bad stream\n";
}
}
This provides a clean interface and outputs the same for both the console and the file. You may want to add a flush method or open the file in append mode.
Solution 2
You can swap the underlying buffers. Here is that done facilitated through RAII.
#include <streambuf>
class buffer_restore
{
std::ostream& os;
std::streambuf* buf;
public:
buffer_restore(std::ostream& os) : os(os), buf(os.rdbuf())
{ }
~buffer_restore()
{
os.rdbuf(buf);
}
};
int main()
{
buffer_restore b(std::cout);
std::ofstream file("file.txt");
std::cout.rdbuf(file.rdbuf());
// ...
}
Solution 3
I assume you have some code using std::cout
and printf
which you cannot modify, otherwise the most simple way to solve your problem would be to write to a different stream from cout
and use fprintf
rather than or in conjunction with printf
.
By following that approach you could define both a new stream class that actually wrote both to standard output and to a given file, as well as a function that combined calls to both printf
and fprintf
.
However a much simpler approach is to use the tee
program, originally from UNIX, which copies its input both to output and to a given file. With that you could simply call your program in this way:
your_program | tee your_log_file
Answers to this question lead to a few alternative implementations available for Windows. Personally I always install cygwin on my PC's to have UNIX/Linux utilities available.
Related videos on Youtube

Rasmi Ranjan Nayak
Always ready for programming. Favorite Programming Languages C, C++, Python, Java, Android
Updated on June 18, 2022Comments
-
Rasmi Ranjan Nayak 11 months
I have a requirement, I need to use
printf
andcout
to display the data intoconsole and file
as well. Forprintf
I have done it but forcout
I am struggling, how to do it?#ifdef _MSC_VER #define GWEN_FNULL "NUL" #define va_copy(d,s) ((d) = (s)) #else #define GWEN_FNULL "/dev/null" #endif #include <iostream> #include <fstream> using namespace std; void printf (FILE * outfile, const char * format, ...) { va_list ap1, ap2; int i = 5; va_start(ap1, format); va_copy(ap2, ap1); vprintf(format, ap1); vfprintf(outfile, format, ap2); va_end(ap2); va_end(ap1); } /* void COUT(const char* fmt, ...) { ofstream out("output-file.txt"); std::cout << "Cout to file"; out << "Cout to file"; }*/ int main (int argc, char *argv[]) { FILE *outfile; char *mode = "a+"; char outputFilename[] = "PRINT.log"; outfile = fopen(outputFilename, mode); char bigfoot[] = "Hello World!\n"; int howbad = 10; printf(outfile, "\n--------\n"); //myout(); /* then i realized that i can't send the arguments to fn:PRINTs */ printf(outfile, "%s %i",bigfoot, howbad); /* error here! I can't send bigfoot and howbad*/ system("pause"); return 0; }
I have done it in
COUT
(caps, the commented part for the code above) . But I want to use normalstd::cout
, so how can I override it. And it should work for bothsting and variables
likeint i = 5; cout << "Hello world" << i <<endl;
Or are there anyway to capture
stdout
data, so that they can be easily written intofile and console
as well. -
Filip Roséen - refp over 9 years-1; the answer by not-rightfold might not be the most detailed, but that's how you do it.
-
Rasmi Ranjan Nayak over 9 yearsYou are right. I have a mix of
printf
andcouts
on the top of all these I do have third party libraryg-test and g-mock
where I can not redirect all thecouts
to my user defined way. so how should I proceed? -
MSalters over 9 years@RasmiRanjanNayak: If your third-party library uses the same C++ library, it shares the same
std::cout
object. In that case, not-rightfold's answer usingstd::cout.rd_buf
will work because it changes the singlestd::cout
object. If the library usesprintf
, you may have bigger problems. -
MSalters over 9 yearsBad idea. The formatting between the two streams is kept in two distinct stream objects, which can become out of sync. Easily, in fact, since the
std::cout
object is still accessible outside your calss. Furthermore, your stream isn't anostream
so it can't be passed to a function expecting one. Finally, I don't think you can use evenstd::endl
on your stream. -
stefan over 9 years@MSalters I'm only providing a minimal working implementation. Surely one can inherit from ostream and your second point is gone. I hate using std::endl, but it's not that hard to copy that behaviour as well. Not modifying std::cout is the whole point of my answer..
-
Joe Beuckman about 9 yearsThis is working great to trap std::cout so I can build an ncurses interface for a large existing program. Thank you!
-
HAL9000 almost 3 yearshere the question is "how to do it", not "should I do it". You should have provided your useful (in some cases) advice after providing the answer to the specific question