Implementing a "debug text output class" for my classes

Started by
3 comments, last by hallgeir 16 years, 2 months ago
Hi. :) I'm in the process of trying to clean up my code a bit, and while doing so I thought I should implement some kind of debug text outputter to use with all my classes. I did make one (a long time ago) but it's very poorly designed and I got a new idea. What I had in mind was something like this (simplified):

#include <ostream>

class Debug
{
private:
	std::ostream &outstream
public:
	Debug(std::ostream &output);
	void print(std::string dbgtext);
};
So basically, the idea is: Let the user of the classes decide what stream the debug text should be outputted to (for instance std::cout, an instance of std::ofstream, or similar). That part is done. BUT what I also had in mind was to let that decision apply for EVERY class in my project. Or else this is pretty useless. Let's say I want to let all the debug text get outputted to a file called "debug.txt". Then I'd like to only have to call the constructor ONCE, and then let every class use that output stream. For instance: std::ofstream debugfile("debug.txt"); Debug debugobject(ofstream); should make ALL my classes (texture class, sprite class, everything) output to "debug.txt". How is the best way to achieve this? I've thought of a few options but they all seem VERY inconvenient. The ones I thought of was: - Have a reference to the debug object in every class. Unfortunately then I'd have to include the debug object in the CONSTRUCTOR of every class. - Pass the debug object as a reference to all my member functions. - Make it a global variable in my namespace. Personally I'm not very fond of this one. Neither of those options seems like a good idea to me. So how would you do it? Any suggestions? :) Thanks in advance.
Advertisement
It depends on your needs. If your game is simple enough, I see nothing wrong with a global logger.

If you decide to do this, there is a neat trick. You can use the rdbuf() member of std::ostream to change the location of the output. So what you could so is:
int main(){    std::ofstream file("debug.txt");    std::cout.rdbuf(file.rdbuf());    // and std::cerr, std::clog        std::cout << "Hello, world\n"; // <-- written to the file!}


You could even implement your own std::streambuf to log to multiple locations at once. This way you don't have to write your own class, and you get all the benefits of a proper std::ostream (including support for user defined objects).

Even if you don't plan on using a global using this method could be handy to write the Log class itself. If you are interested here are some links:
Bregma's post towards the end.
Bregma again. [smile]
Mr Edd's blog entry on the subject.
Cheers rip-off! Thanks for the tip. Also I will certainly look into implementing my own streambuf.

Any further tips on how to avoid using a global logger is also very appreciated. :) I might make it global, if I don't get any bright ideas (from myself or you guys) but I'd really hoped I don't need to.

Best regards
I do what rip-off does + have a overloaded << outside of the class like this. It feels a bit nicer than having a DebugString() in every class.

template <class type>inline std::ostream& operator << (std::ostream& stream, const vec2<type>& v) {	stream << "(" << v.x << ", " << v.y << ")";	return stream;}//so i can writevec2f v;std::cout << v << std::endl;
Quote:Original post by Thergothon
I do what rip-off does + have a overloaded << outside of the class like this. It feels a bit nicer than having a DebugString() in every class.


Ah cool. Good idea. *notes* :) I could really use a better way to print debug info about my classes, and this one looks exactly what I'm looking for.

Anyway, here's my plan so far. A few changes:
I think I will use std::clog / std::err consistently through my code. That means - no real need for a logging class (at least not for now). Then I'll use rip-offs suggestion about redirecting std::clog to use another stream (like a ofstream instance or cout). This can hopefully be done globally, for instance doing it once in my main function should hopefully also apply in all my classes. This remains to be tested though. :P

Thanks for the help so far! :)

Also any further tips on logging is greatly appreciated!

Kind regards

This topic is closed to new replies.

Advertisement