c++singletonlnk2019

C++ Singleton LNK2019 - "Unresolved external symbol (private static) referenced in function (private static)"


Having trouble implementing a singleton class (using tutorial from GeeksForGeeks). I have another class that is implemented the same, however the same issue is not occuring for that class. I have looked at lots of similar questions and tutorials but nothing is mentioning this particular issue, or if they are their solutions are already implemented here (as far as I can tell)

Header file (simplified)

class ActionLogger
{
public:
    static ActionLogger* getInstance();

private:
    ActionLogger();
    ActionLogger(const ActionLogger& obj) = delete;

   static ActionLogger* _instance;

}

cpp file:

ActionLogger* ActionLogger::_instance = NULL;

ActionLogger* ActionLogger::getInstance()
{
    if(_instance == NULL)
    {
        _instance = new ClassName();

    }

    return _instance;
}

Error Message:

error LNK2019: unresolved external symbol "private: __cdecl ActionLogger::ActionLogger(void)" (??0ActionLogger@@AEAA@XZ) referenced in function "public: static class ActionLogger * __cdecl ActionLogger::getInstance(void)" (?getInstance@ActionLogger@@SAPEAV1@XZ)

Sorry if this has been answered elsewhere, I have looked but sincerely couldn't find it.


Solution

  • Aside from the missing constructor, which you could also just declare as =default; I'd generally recommend doing singletons differently:

    ActionLogger& ActionLogger::getInstance()
    {
       static ActionLogger instance;
       return instance;
    }
    
    

    This forces everyone to go through getInstance, and it's also thread-safe in case you ever get to this kind of stuff.

    Also, as you can see, I've changed the return value from a pointer to a reference. It's something I prefer doing to indicate that you always get the object -- if something returns a raw pointer, it's (almost) always because it can be a nullptr to indicate certain kinds of problems.

    If you're running into cleanup isses at program exit, because C++ doesn't care whether anyone is still using your instance, you can also prevent cleanup like this:

    ActionLogger& ActionLogger::getInstance()
    {
       static ActionLogger& instance=*new ActionLogger();
       return instance;
    }
    

    In this case, you can actually =delete the destructor, if you want to.