Quote:Original post by Arcibald Wearlot
My point is that there is a much simpler solution: the LogFile doesn't need to be a class. Its functions could just go in a namespace, including Init() and Term(). The code, in my opinion, is more clean, and encapsulation is better because all the private members of CLogFile are hidden in LogFile.cpp. There are less #include files in the header, resulting in faster compile times and less dependencies.
On the other hand, look at the disadvantages. If you ever decide, well, you really do need a second LogFile, basically all your code using that "class" will break. Since nobody can perfectly predict their future needs, this means that you'll end up rewriting more code. Maybe not for LogFile, but for some other class where you used the same logic. The problem is that by reducing it to these "bare essentials", everything using that code has to be aware of those "bare essentials" - which in this case, involves "there's only one LogFile".
The problem arises with:
1) Directly using singletons2) Directly using globals3) Directly using any single instance of the class
Let's apply this to the wonderful world of "Hello, World!".
The simplest implementation directly uses the global std::cout:
#include <iostream>void greet( void ) { std::cout << "Hello, "; std::cout << " World!"; std::cout << std::endl;}int main () { greet();}
Okay, so I made this example a little more complicated than it needed to be. But, it better illustrates a repeated use of globals, as we might use them in a more complex scenario. What happens we decide, okay, we want to save this wonderful greeting of ours to a file? greet() has to be entirely rewritten. The same occurs if we're using a singleton.
Now, let's change things a bit. Instead of having greet() directly use the global std::cout, let's have it take a paremeter:
#include <iostream>void greet( std::ostream & os ) { os << "Hello, "; os << " World!"; os << std::endl;}int main() { greet( std::cout );}
Just another way of implementing the same thing, right? The advantage here, though, is that greet is blissfully unaware that it's using std::cout. It dosn't need to know, there's only one stream. When we want to output to a file, we need only rewrite main(), where we only have to replace one instance of std::cout, instead of 3:
int main() { std::ofstream file( "greeting.txt" ); greet( file );}
Not only that, but our program can now use multiple streams, whereas greet was formerly hardcoded to only using one:
int main() { std::ofstream file( "greeting.txt" ); greet( file ); greet( std::cout );}
The cost? An extra reference/pointer as a parameter/class-member (without which, greet would hardly be "much simpler"). The gain? Flexibility.
As for the "class Collision" thing might be to deal with older compilers that don't support namespaces well. That's the only real reason I can think of for an all-statics class like that.