Пользовательский класс c++ cout-вывод в консоль и файл журнала

Я работаю над программой, которая активно использует "cout

Я использую Visual Studio 2008. Я видел сообщение в группы Google: перенаправить cout в файл, который, похоже, делает именно то, что я хочу сделать. Единственная проблема в том, что код не компилируется. Я получаю ошибки C2248 "не могу получить доступ к защищенному члену" при вызовах метода- >overflow() и - >sync ().

кто-нибудь знает, как заставить этот код компилироваться? Или альтернативный способ перенаправления cout на консоль и файл одновременно?

7 ответов


на sync вызовы могут быть заменены на pubsync. Что касается overflow звонок я думаю, что это может быть опечатка. как это выглядит, как будто это должен быть вызов sputc.


на boost::iostreams::tee_device для этого

#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>

#include <fstream>
#include <iostream>

int
main()
{
    typedef boost::iostreams::tee_device<std::ostream, std::ofstream> Tee;
    typedef boost::iostreams::stream<Tee> TeeStream;

    std::ofstream file( "foo.out" );
    Tee tee( std::cout, file );

    TeeStream both( tee );

    both << "this goes to both std::cout and foo.out" << std::endl;

    return 0;
}

пример вызова:

samm$ ./a.out
this goes to both std::cout and foo.out
samm$ cat foo.out
this goes to both std::cout and foo.out
samm$ 

Если вы в отчаянии:

#define protected public
#include <iostream>
#undef protected

это грубый хак, но он обычно работает.


что вы можете сделать, это захватить std::cout.rdbuf() с указателем std::streambuf, тогда я думаю, что вы должны иметь возможность записывать все выходы в std::cout в какой-нибудь файл.


Это легко распространяется на дополнительные потоки.

OstreamFork.hpp -- распределить данные по 2 потокам одновременно

#include <iomanip>
#include <fstream>
#include <iostream>
using namespace std ;

class ostreamFork           // Write same data to two ostreams
{
public:
  ostream& os1 ;
  ostream& os2 ;

  ostreamFork( ostream& os_one , ostream& os_two )
  : os1( os_one ) ,
    os2( os_two )
  {}

 } ;

                          // For data: int, long , ...
 template <class Data>
 ostreamFork& operator<<( ostreamFork& osf , Data d )
 {
   osf.os1 << d ; 
   osf.os2 << d ;
   return osf ;
 }
                        // For manipulators: endl, flush
 ostreamFork& operator<<( ostreamFork& osf , ostream& (*f)(ostream&)  )
 {
   osf.os1 << f ; 
   osf.os2 << f ;
   return osf ;
 }

                            // For setw() , ...
template<class ManipData>
 ostreamFork& operator<<( ostreamFork& osf , ostream& (*f)(ostream&, ManipData )  )
 {
   osf.os1 << f ; 
   osf.os2 << f ;
   return osf ;
 }

TestOstreamFork.cpp:

#include "stdafx.h"
#include <fstream>
  using namespace std ;
#include "ostreamFork.hpp"

int main(int argc, char* argv[])
{
  ofstream file( "test2.txt" ) ;
  ostreamFork osf( file , cout ) ;

  for ( int i = 0 ; i < 10 ; i++ )
  {
    osf << i << setw(10) << " " << 10*i << endl  ;
  }

    return 0 ;
}

выход как на cout, так и на test2.txt:

0          0
1          10
2          20
3          30
4          40
5          50
6          60
7          70
8          80
9          90

вы можете просто использовать класс-оболочку для этого, что-нибудь подобное

#include <iostream>
#include <fstream>

...

class streamoutput
{
    std::ofstream fileoutput;
    public:
    streamoutput(char*filename){
        fileoutput.open(filename);
    }
    ~streamoutput(){
        fileoutput.close();
    }
    template<class TOut> streamoutput& operator <<(const TOut& data)
    {
        fileoutput << data;
        std::cout << data;
        return this;
    }
};

extern streamoutput cout("logfile.log");

объявить cout как это и просто изменить все ваши #include <iostream> чтобы включить эту обертку (remeber cout-внешняя переменная, поэтому вам также нужно декларировать ее в одном из ваших исходных кодов).


Извините, что так поздно, но это должно быть решение с перенаправлением cout на teebuffer на основе решения Дитмара Кюля в Google groups.

использование просто

GetSetLog log("myfile.log");

в течение жизни объекта " log " все будет записано как в cout/cerr, так и в file

https://sourceforge.net/p/getset/code/ci/master/tree/GetSet/GetSetLog.hxx