views:

56

answers:

4

I have an ErrorLog class, that is used to write and modify log files. I'd like to write to it before and after major events for debugging purposes and I only want to use one instance of the ErrorLog class for the entire application. I tried declaring an ErrorLog object as a global by placing

ErrorLog exe_log;
into a header file so it is accessbile to other files, but I keep getting an error saying it is already defined. Is there a correct way to defing global objects?

+1  A: 

You should define it like that in a single source file, and declare it in a header as:

extern ErrorLog exe_log;

Having said that, using global variables or class instances is frowned upon. You should get in the habit of trying to avoid that as much as possible.

A design pattern known as Singleton has been proposed to deal with such cases, although nowadays many developers, for good reasons, highly discourage its use.

UncleZeiv
+4  A: 

You need a declaration in a header file and a definition in a source file.

foo.h:

extern ErrorLog exe_log;   // declaration (note the "extern")

foo.cpp:

ErrorLog exe_log;          // definition

bar.cpp:

#include "foo.h"
FredOverflow
+1 for giving the correct answer and for not suggesting the singleton design (anti-)pattern.
James McNellis
@james: while I do agree that there are good reasons to avoid singletons, I don't agree on downvoting answers mentioning it: it is seen by many people as a legitimate pattern and knowing about it is culturally important I think, when you deal with global instances of classes.
UncleZeiv
Although I purposely hate Singletons, I understand that it is a (somewhat) valid choice and so I am upvoting to cancel out all the unnecessary downvotes.
mathepic
Singletons are not a valid choice. You use them as a crutch to support other poorly designed code. It's like using a macro to spam overloads instead of accepting that you need variadic templates.
DeadMG
thanks everyone for all of these great answers. It seems like the singleton pattern is not a 'best practice' so I am just going to avoid it by making an ErrorLog object a member of my AppManager class, which will control log writing.
Dooms101
@Dooms101 - Well, this is technically a Singleton in a way, since Singleton is just another name for 'global variable'. But at least its honest. :-) Even the most die-hard opponents of the Singleton pattern and global variables in general think that logging is one of the very few exceptions to the rule, maybe.
Omnifarious
@Omni: No, it isn't. You can have as many global variables of type `ErrorLog` as you want with my approach, but with a Singleton, you restrict yourself to exactly one (for no particular reason imho).
FredOverflow
Singletons are bad precisely because they are the same as global variables. It's a fallacy to think that a "proper" global variable is somehow more correct than a singleton, or vice-versa.
Ken Simon
@Ken: How can Singletons and global variables be the same when I can have only one instance of a Singleton type but as many as I want if I don't follow the Singleton pattern?
FredOverflow
@Fred, you're totally right. I just think the "number of instances" is pretty irrelevant, since I (and I'm only speaking of myself personally) don't really view Singletons as classes in and of themselves, but more of just gateways for accessing a global object. If you want more than one, create more than one singleton class (The classic example being "Error Log" and "Warning Log" which are both singletons, but both return an object of type "Log".)
Ken Simon
A: 

I think you are looking for the Singleton Pattern. You should have a static member of the type ErrorLog* in your ErrorLog class and initialise it with a create function, similar to this:

// .h file
class ErrorLog {
  public:
    ErrorLog* create() {
      if (!this->log)
        this->log = new ErrorLog();
      return this->log;
    }
  private:
    static ErrorLog* log;
    ErrorLog() {}
}
// .cpp file
ErrorLog* ErrorLog::log = NULL;
bitmask
While I will not down-vote you for mentioning Singleton, I will not upvote you. Here is a really excellent discourse on why the Singleton pattern is almost always a bad idea: http://www.object-oriented-security.org/lets-argue/singletons
Omnifarious
I agree. I try to avoid singletons (globals) at all costs, but the OP asked not for my opinion on the topic but for a way to implement it. Whether you have a global variable and can keep feeling superior because you are one of the smart guys that *hate patterns*, or have a singleton class to avoid global scope, is none of my concern. I don't care about up/down-votes, but is the task bad or the solution?
bitmask
@bitmask - I rather like patterns, just not Singleton. :-) And generally, when someone is asking for the best way to do the wrong thing I tell them they're doing the wrong thing, and then sometimes (usually) tell them the best way to do it.
Omnifarious
A: 

I don't know about any "correct" way (at least, the standard doesn't define one afaik). However, one good way to use global objects is to define them using the singleton pattern. In your case, this would translate to declaring a static member in your ErrorLog class with the type of ErrorLog. This way, the global object will not be in the global scope (which can be dangerous in some cases).

CreoValis