2011-12-09 29 views
8

Mam klasę C++, którą chciałbym przechowywać strumień używany do logowania.Strumień C++ jako zmienna składowa

Strumień powinien móc być ustawiony (i ewentualnie zresetowany) po skonstruowaniu obiektu.

Powinno być możliwe ustawienie strumienia jako std::cout, lub jako strumień plików do zalogowania się do pliku, lub jako strumień tekstowy, który nie powoduje nic więcej niż zignorowanie danych (sortowanie /dev/null). W każdym razie powinien to być obiekt typu ostream, który twórca obiektu może zresetować w dowolnym momencie. Klasa sama w sobie nie jest świadoma rodzaju strumienia betonu.

mógłbym tego dokonać za pomocą wskaźnika do ostream, ale składnia staje się trochę denerwujące, konieczności użycia operatora deref:

(*m_log) << "message"; 

zamiast

m_log << "message"; 

ale mogę Używaj referencji, ponieważ obiekt strumienia musi zostać ewentualnie zresetowany po zainicjowaniu obiektu.

Czy istnieje elegancki sposób, aby to osiągnąć, tj. Uniknąć stosowania wskaźników, ale nadal można zresetować po zakończeniu budowy?

+2

Dlaczego nie zapewniają niewielką funkcję składową powracającego odniesienie do strumienia? coś na drodze: ostream & mlog() {return * m_log;}. Napisalibyśmy wtedy: mlog() << "wiadomość"; – fjardon

+0

Użyj wskaźnika i zacznij swoją funkcję od 'std :: ostream & o = * m_log;'. –

+2

@fjardon: Dlaczego nie podasz tego jako małą odpowiedź? ; P – Xeo

Odpowiedz

9

Można zresetować strumienie: zobaczyć go na żywo na https://ideone.com/Ci4eo

#include <fstream> 
#include <iostream> 
#include <string> 

struct Logger 
{ 
    Logger(std::ostream& os) : m_log(os.rdbuf()) { } 

    std::streambuf* reset(std::ostream& os) 
    { 
     return m_log.rdbuf(os.rdbuf()); 
    } 

    template <typename T> friend Logger& operator<<(Logger& os, const T& t) 
    { os.m_log << t; return os; } 

    friend Logger& operator<<(Logger& os, std::ostream& (*pf)(std::ostream&)) 
    { os.m_log << pf; return os; } 

    private: 
    std::ostream m_log; 
}; 

int main(int argc, const char *argv[]) 
{ 
    Logger logto(std::cout); 

    logto << "Hello world" << std::endl; 

    logto.reset(std::cerr); 
    logto << "Error world" << std::endl; 

    return 0; 
} 
+0

To jest dobre rozwiązanie, dokładnie na wzór tego, co szukałem dla. Mogłoby zostać rozszerzone do (opcjonalnie) dodania drugiego strumienia, na przykład do utworzenia T. Poprawiłbym to ... gdybym miał dość reputacji. (: Dzięki. –

+0

Jeśli szukasz obiektów takich jak strumienie Tee, zajrzyj do [Boost Iostreams] (http://www.boost.org/doc/libs/1_48_0/libs/iostreams/doc/index. html? path = 1), np. [Tee Filter] (http://www.boost.org/doc/libs/1_48_0/libs/iostreams/doc/functions/tee.html#tee_filter) w połączeniu z [Pipelines] (http://www.boost.org/doc/libs/1_48_0/libs/iostreams/doc/guide/pipelines.html) – sehe

4

Po co się kłopotać?

Zamiast tego wystarczy użyć log() << "blah\n";.

+1

Masz na myśli 'return * m_log;' w funkcji, oczywiście. –

+1

@ James: Nie mam pojęcia, co masz na myśli. ♪ – Xeo

+0

Nie było żadnej * metody rejestrowania zanim odświeżyłem stronę. –

Powiązane problemy