1

Hi I have implemented a singleton pattern in c++ with the VS2010 and the compiler throw me an error !!

#ifndef __EgEngine__ 
#define __EgEngine__ 1

#include <esUtil.h>
#include <stdlib.h>
#include <EgGpuManager.h>

class   EgEngine
{
public:
    EgEngine();
    static EgGpuManager GetGpuManager();
    ~EgEngine();
    void EgInit();

private:
    EgEngine(const EgEngine &other){};
    EgEngine* operator = (const EgEngine &other)const {};
    static EgGpuManager GpuManager; // Return this !! 
    ESContext esContext;
};

#endif

The other class

#ifndef __EgGpuManager__
#define __EgGpuManager__ 1

#include <EgBuffer.h>
#include <EgProgram.h>


    class EgGpuManager
    {
    public:
        EgBuffer* GetBuffer();
        EgProgram* GetNewProgram();

    private:
        EgGpuManager();
        ~EgGpuManager();
        EgBuffer buffer;
    };

#endif

And when I try to compile I have this error:

1>EgEngine.obj : error LNK2001: 
unresolved external symbol "private: static class
EgGpuManager EgEngine::GpuManager" (?GpuManager@EgEngine@@0VEgGpuManager@@A)

Help me please and thanks.

Eduard
  • 11
  • 1
  • possible duplicate of [static member variable in a class](http://stackoverflow.com/questions/5601051/static-member-variable-in-a-class) – Mark B Jul 29 '11 at 18:03
  • 1
    [Don't use singletons](http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/). They are not cool. They are hard to implement correctly, near-impossible in a multi-threaded environment, and even when they're implemented correctly, they still only serve to make your code worse. – jalf Jul 29 '11 at 18:37
  • 1
    Also, names like `__EgEngine__` should be avoided. Names containing a double underscore, or which begin with an underscore followed by a capital letter are reserved for use by the implementation (the compiler and standard library) (Finally, it is common practice to make macros ALL UPPERCASE), so it should be `EGENGINE`, not `EgEngine`. – jalf Jul 29 '11 at 18:40

3 Answers3

4

static EgGpuManager GpuManager; // Return this !! this guy has to be instantiated somewhere in your C++ code.

static class members have to appear in the global scope, so in the C++ file add:

EgGpuManager EgEngine::GpuManager.

By the way, you have a private constructor for EgGpuManager class, which will be a problem in this case because it is created by EgEngine. You're not implementing the singleton correctly. Use a static EgGpuManager *EgGpuManager::Get() method to return an instance, and it will instantiate the class on the first call, then you can do it with a private constructor. Otherwise make them friends.

littleadv
  • 20,100
  • 2
  • 36
  • 50
  • Where I need to put the "EgGpuManager EgEngine::GpuManager;" ?? – Eduard Jul 29 '11 at 18:02
  • @Eduard - in one of the C++ files, I would suggest the one with the implementation of the `EgEngine` class. – littleadv Jul 29 '11 at 18:06
  • I have the same problem. #ifndef __EgEngine__ #define __EgEngine__ 1 #include #include #include class EgEngine { static EgGpuManager EgEngine::GpuManager; public: EgEngine(); static EgGpuManager GetGpuManager(); ~EgEngine(); void EgInit(); ESContext esContext; private: EgEngine(const EgEngine &other){}; EgEngine* operator = (const EgEngine &other)const {}; // static EgGpuManager GpuManager; }; #endif – Eduard Jul 29 '11 at 18:31
  • @Eduard you do know what "global scope" means, don't you? Read here: http://stackoverflow.com/questions/5601051/static-member-variable-in-a-class. – littleadv Jul 29 '11 at 18:39
0

The line "static EgGpuManager GpuManager;" inside the class declaration of EgEngine is only a declaration: You're saying that this object will exist somewhere. The linker complains that it did not find the object anywhere. To solve this, place an instantiation in one of your source files (in global scope):

EgGpuManager EgEngine::GpuManager;
Stefan Majewsky
  • 5,427
  • 2
  • 28
  • 51
0

You must put the instantiation of the singleton object either in the global scope, as suggested by other answers, or in the implementation of GetGpuManager() like this :

EgGpuManager& EgEngine::GetGpuManager()
{
  static EgGpuManager GpuManager;
  return GpuManager;
}

In this case you need to remove the declaration of GpuManager from the class definition. Also note the & to return a reference, as you certainly don't want to return a copy of the object (that would defeat the purpose of making a singleton). The advantage here is that the object will not be created until GetGpuManager() is called for the first time, whereas all statics in global scope are created when the program starts.

dhenot
  • 321
  • 1
  • 5