views:

207

answers:

6

Hello all general question is i like to build logger class that writes to single log file from different classes in my application what should the logger class be singletone or static class

+2  A: 

In C++ you'll want a singleton rather than a static. C++ does not allow you to control the order static objects are constructed and destructed, and if you tried to log before the static was constructed behaviour would possibly be undefined.

I'm not sure about Java.

Stephen Nutt
c++ is what i need,thanks
A: 

The answer is of course "it depends."

First of all if I were you I would not reinvent the wheel and just use Log4j. If it does not serve your exact requirement, you are probably better off extending the one component of log4net that does not serve your needs (eg a custom loggin source) than startng from scratch. Secondly, a static class might be good enough for a simple logging class. For something more complex, a singleton class might be the way to go.

Justin Dearing
A: 

Don't use singleton or static, use Dependency Injection, i.e instantiate one instance in your main(), and pass a reference to that one instance to all dependent classes. Static and/or singleton is almost never necessary and quite often result in less elegant code.

disown
It doesn't sound like the DI described in http://en.wikipedia.org/wiki/Dependency_injection. And I don't think explicitly passing a non-vital parameter to every function and class is more elegant than requesting one when necessary.
KennyTM
Why is this downvoted? Whether or not it qualifies as DI, it's pretty sensible advice. The only drawback is that it can be a bit of a chore to pass a logger reference around throughout your program. +1 from me to compensate. It's not always the *best* strategy, but it's a perfectly valid one, and far far better than smearing singletons all over your application.
jalf
+5  A: 

What makes you think it should be either? What about a regular non-static class which can be instantiated on demand? And then make a single static instance of it available as the default logger. That way you get the best of both worlds: convenient global access to the logger and the ability to test it or temporarily use a different logger.

Another suggestion is to simply create a single instance and pass it as a parameter to every component of your class, as @disown suggests.

But if you make the class itself static or a singleton, you're just shooting yourself in the foot.

Edit
Example, in response to @Stephen's comment:

// define a logger class, a perfectly ordinary class, not a singleton, and without all static members
class Logger {
 // ....
};

// create a single global *instance* of this class
Logger defaultLog;

void foo() {
  // and now use the globally visible instance
  defaultLog.Log("hello");

  // or create a new one if that's what we need:
  Logger newlog;
  newlog.Log("hello");
}

There's no magic. This is exactly what the standard library does. std::cout isn't a singleton. It is simply a global instance of class std::ostream, a class which can also be instantiated normally if and when you need it.

jalf
I'm not sure I understand your suggestion. Are you expecting every class that needs it to create a new logger object for logging? How is using a single "defaultLogger" instance any different than a singleton? How does your solution give you "the ability to test it" better than the alternatives? If everyone is instantiating their own loggers, how can your system "temporarily use a different logger"?It's strange you got +4 and disown got -1.
Stephen
@Stephen: Check my edit.
jalf
Stephen
Yep. But if that happens, I'd say you have a much more fundamental problem. The one known as *"why the hell do you have so many complex static objects with complex initialization/destruction behavior?"* Then the solution is not to create *more* complex static data in the form of singletons, but to *eliminate* some of your statics. Your program is supposed to run inside the main function, not before it.
jalf
A: 

In C++, you would use this idiom for lazy initialization:

Foo& getInstance()
{
    static Foo instance;
    return instance;
}
FredOverflow
which isn't thread-safe on most compilers. :)
jalf
it's fine on gcc.
Stephen
A: 

I would probably use a singleton, but either way, hide it behind a function or macro. Don't make people type

MySuperSpectacularLogger::GetInstance()->Log("adssdf");

Instead use:

void Log(cpnst string& msg) {
  MySuperSpectacularLogger::GetInstance()->Log(msg);
}

or even better:

// Logs 'msg' with the filename and line number that generates it.
#define LOG(msg) \
  MySuperSpectacularLogger::GetInstance()->Log(__FILE__, __LINE__, msg);
Stephen