2011-07-29 70 views
1

您好我已经在VS2010中使用C++实现了一个单例模式,并且编译器给我一个错误!Singleton模式C++错误

#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 

其他类

#ifndef __EgGpuManager__ 
#define __EgGpuManager__ 1 

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


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

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

#endif 

当我尝试编译我有这样的错误:

1>EgEngine.obj : error LNK2001: 
unresolved external symbol "private: static class 
EgGpuManager EgEngine::GpuManager" ([email protected]@@[email protected]@A) 

请帮助我和感谢。

+0

可能重复[静态成员变量在类中](http://stackoverflow.com/questions/5601051/static-member-variable-in-a-class) –

+1

[不要使用单身人士](http: //jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/)。他们并不酷。在多线程环境中,它们很难正确实现,几乎不可能实现,即使它们正确实现,它们仍然只会使代码变得更糟。 – jalf

+1

此外,应避免像__EgEngine__这样的名称。包含双下划线的名称,或者以下划线开头,后跟大写字母的名称被保留供实现(编译器和标准库)使用(最后,制作宏ALL UPPERCASE是常见做法),所以它应该是' EGENGINE',而不是'EgEngine'。 – jalf

回答

4

static EgGpuManager GpuManager; // Return this !!这个人必须在你的C++代码中的某个地方实例化。

static类成员必须出现在全球范围内,所以在C++文件中加入:

EgGpuManager EgEngine::GpuManager

顺便说一句,你有一个EgGpuManager类的私人构造函数,在这种情况下这将是一个问题,因为它是由EgEngine创建的。你没有正确实施单身人士。使用static EgGpuManager *EgGpuManager::Get()方法返回一个实例,它将在第一次调用时实例化该类,然后可以使用私有构造函数来实现。否则让他们friend s。

+0

我需要把“EgGpuManager EgEngine :: GpuManager;” ?? – Eduard

+0

@Eduard - 在其中一个C++文件中,我会建议使用'EgEngine'类的实现。 – littleadv

+0

我有同样的问题。的#ifndef __EgEngine__ 的#define __EgEngine__ 1 的#include 的#include 的#include 类\t EgEngine { 静态EgGpuManager EgEngine :: GpuManager; public: \t EgEngine(); \t static EgGpuManager GetGpuManager(); \t〜EgEngine(); \t void EgInit(); ESContext esContext; private: \t EgEngine(const EgEngine&other){}; EgEngine * operator =(const EgEngine&other)const {}; // \t static EgGpuManager GpuManager; }; #endif – Eduard

0

行“static EgGpuManager GpuManager;”在EgEngine的类声明中,只有一个声明:你说这个对象将存在某个地方。链接器抱怨说它没有在任何地方找到对象。为了解决这个问题,将在您的源文件之一的实例(全球范围):

EgGpuManager EgEngine::GpuManager; 
0

你必须把单对象的实例化无论是在全球范围内,由其他答案的建议,或在GetGpuManager()实施这样的:

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

在这种情况下,你需要从类定义中删除GpuManager的声明。还要注意&要返回一个引用,因为你当然不希望返回该对象的副本(这会破坏制作单例的目的)。这样做的好处是,只有第一次调用GetGpuManager()时才会创建对象,而全局范围内的所有静态都是在程序启动时创建的。