Eigene Log-Klasse erstellen, mit Stringstream
-
Hallo Leute,
ich bin gerade Dabei mir eine Log-Klasse zu erstellen, dazu hätte ich ein paar Fragen ...
Hier erstmal das, was ich schon hab:
log.h
#ifndef _log_h_ #define _log_h_ #include <iostream> #include <fstream> #include <string> #include <sstream> class CLog { public: std::stringstream &data; std::ostream &os; #ifdef NDEBUG std::ofstream &of; std::string file; #endif public: CLog(); #ifndef NDEBUG CLog(std::stringstream &data, std::ostream &os = std::cout); #else CLog(std::string &file = "log.log"); CLog(std::stringstream &data, std::string &file = "log.log"); #endif CLog(const CLog &log); virtual ~CLog(); public: CLog operator=(const CLog &log); void operator<<(const CLog &log); #ifndef NDEBUG friend std::ostream& operator<<(std::ostream &os, CLog &log); #else friend void operator<<(std::ofstream &of, CLog &log); #endif template<typename LOG> void operator<<(LOG log); friend CLog operator<<(CLog log, int buff); friend CLog operator<<(CLog log, std::string buff); }; #endif //_log_h_log.cpp
#include "log.h" using namespace std; //Konstruktoren #ifndef NDEBUG CLog::CLog() : os(cout), data(){ } #else CLog::CLog() : os(cout), data(), of(){ #ifdef NDEBUG this->file = "log.log"; ofstream of; of.open(this->file.c_str()); of.close(); #endif } #endif #ifndef NDEBUG CLog::CLog(stringstream &data, ostream &os) : data(data), os(os){ } #else CLog::CLog(string &file) : of(), data(), os(cout), file(file){ ofstream of; of.open(this->file.c_str()); of.close(); } CLog::CLog(stringstream &data, string &file) : of(), data(data), os(cout), file(file){ ofstream of; of.open(this->file.c_str()); of.close(); } #endif #ifndef NDEBUG CLog::CLog(const CLog &log) : os(cout), data(){ stringstream ss; ss.str(""); ss.clear(); ss<<log.data.str(); } #else CLog::CLog(const CLog &log) : os(cout), data(), of(){ this->data.str(""); this->data.clear(); this->data<<log.data; } #endif //Destruktor CLog::~CLog(){ } //Operatoren CLog CLog::operator=(const CLog &log){ this->data.str(""); this->data.clear(); this->data<<log.data; return *this; } void CLog::operator<<(const CLog &log){ this->data.str(""); this->data.clear(); this->data<<log.data; #ifndef NDEBUG this->os<<*this; #else this->of<<*this; #endif } #ifndef NDEBUG ostream& operator<<(std::ostream &os, CLog &log){ return os<<log.data.str().c_str(); } #else void operator<<(std::ofstream &of, CLog &log){ of.open((log.file.str()).c_str(), ios::out|ios::app); if(of.good()){ of<<log.data.c_str(); of.close(); } else cout<<log.data.str(); } #endif template<typename LOG> void CLog::operator<<(LOG log){ this->data<<log; #ifndef NDEBUG this->os<<*this; #else this->of<<*this; #endif this->data.str(""); this->data.clear(); } CLog operator<<(CLog log, int buff){ log.data<<buff; #ifndef NDEBUG log.os<<log.data; #else log.of<<log.data; #endif log.data.str(""); log.data.clear(); } CLog operator<<(CLog log, string buff){ log.data<<buff; #ifndef NDEBUG log.os<<log.data; #else log.of<<log.data; #endif log.data.str(""); log.data.clear(); }Hier gleich mal mehrere Fragen:
1. Ist das so in Ordnung mit dem#ifndef NDEBUGoder sollte ich es lieber anders machen?
2. Sollte ich statt Stringstream etwas anderes nehmen?
3. Wenn ich Daten in den Stringstream schreiben will (log.cpp Zeile 43, 49...), Beendet immer mein Programm, ohne Fehler oder Sonstiges
4. Kann ich dann einfach in anderen Klassen einen friend Operator für die Log-Klasse deklarieren?class foo { foo(); ... friend CLog& operator<<(CLog &log, foo &foo_obj); ... };Für Anregungen stehe ich gerne zur Verfügung
Gruß
Simon
-
varginator schrieb:
Hier gleich mal mehrere Fragen:
1. Ist das so in Ordnung mit dem#ifndef NDEBUGoder sollte ich es lieber anders machen?
Im Prinzip ja - aber siehe 2.)
varginator schrieb:
2. Sollte ich statt Stringstream etwas anderes nehmen?
Ja - die Erfinder von den C++-Streams haben dafür das Umschalten eines ostreams vorgesehen. Siehe auch den Parallel-Thread.
varginator schrieb:
3. Wenn ich Daten in den Stringstream schreiben will (log.cpp Zeile 43, 49...), Beendet immer mein Programm, ohne Fehler oder Sonstiges
Der member 'data' ist eine Referenz und wird nicht initialisiert; und führt damit zu undefiniertem Verhalten. - bei mir übersetzt das gar nicht!?
varginator schrieb:
4. Kann ich dann einfach in anderen Klassen einen friend Operator für die Log-Klasse deklarieren?
class foo { foo(); ... friend CLog& operator<<(CLog &log, foo &foo_obj); ... };Ja - aber besser Du deklarierst einen friend-Ausgabe-Operator mit std::ostream& - dafür ist er da. In beiden Fällen sollte es 'const foo& foo_obj' heißen.
Gruß
Werner
-
Hallo Werner,
danke für deine Hilfe, ich hab nur noch ein paar Fragen, wie ich das dann realisieren kann:
zu 1. Ich versteh nich ganz was du damit meinst, wenn ich im Debug-Mode auf cout ausgeben will und im Release auf ostream, dann brauch ich doch defines, oder?
zu 2. Wie würde man das am besten in ner Klasse realisieren?
Kann ich einfach ne streambuf-Variable reinhängen?class CLog { CLog(); std::streambuf* old_stream; //was muss ich dann beim <<-Operator hinschreiben falls ichs mit dem machen will? }; //nochmal mit defines CLog::CLog(){ #ifndef NDEBUG old_stream = clog.rdbuf(cout.rdbuf()); #else std::ofstream logfile("log.txt"); old_stream = clog.rdbuf(logfile.rdbuf()); #endif } int main ( int arg, char* argv[] ) { CLog log; // nirgendwo hin clog << "hello world" << endl; //oder iwie ne Klassenvariable? clog.rdbuf( log.old_stream ); return 0; }zu 3. Aso, ok, aber ohne Referenz hat ers bei mir nich genommen

zu 4. Ja, das kann ich schon machen, aber ich will ja im Release den Output in ne Datei
soll ich da dann defines setzen?Ich will ja den gleichen Aufruf im Debug und im Release, dh. ich gebe
log<<"Text"<<endl;ein, dann soll er im Debug in die Konsole schreiben und im Release in ne Datei
Gruß
Simon
-
Hallo Leute,
ich hab jetzt die Lösung für mein Problem gefunden:
log.h
#ifndef _log_h_ #define _log_h_ #include <fstream> #include <iostream> #include <streambuf> #include <string> class CLog { public: CLog(); CLog(std::string file); ~CLog(); protected: std::streambuf* old_stream; #ifdef NDEBUG std::ofstream of; #endif }; #endif //_log_h_log.cpp
#include "log.h" using namespace std; CLog::CLog(){ #ifndef NDEBUG old_stream = clog.rdbuf(); clog.rdbuf(cout.rdbuf()); #else of.open("log.txt"); old_stream = clog.rdbuf(); clog.rdbuf(of.rdbuf()); #endif } CLog::CLog(string file){ #ifndef NDEBUG old_stream = clog.rdbuf(); clog.rdbuf(cout.rdbuf()); #else of.open(file.c_str()); old_stream = clog.rdbuf(); clog.rdbuf(of.rdbuf()); #endif } CLog::~CLog(){ clog.rdbuf(old_stream); #ifdef NDEBUG of.close(); #endif }main.cpp
#include "log.h" int main(){ CLog log(); clog<<"Hallo Welt"<<endl; cin.get(); return 0; }| EDIT | noch nen Konstruktor hinzugefügt, um die Datei anzugeben
Gruß Simon