我正在编写一个实用程序类库,其中许多是单例.我使用继承实现了它们: template class Tclass Singleton { public: T getInstance() { if(m_instance == 0) { m_instance = new T; } return m_instance; } private: static T*
template <class T> class Singleton { public: T& getInstance() { if(m_instance == 0) { m_instance = new T; } return m_instance; } private: static T* m_instance; }; class SomeClass : public Singleton<SomeClass> { public: SomeClass() {} virtual ~SomeClass() {} void doSomething() {;} };
显然这是一个简单的例子,而不是一个真正的类.无论如何,我发现使用如下代码:
SomeClass::getInstance().doSomething();
将创建SomeClass的多个实例.我想这可能是因为它在我的库(.a)文件之外以及内部使用.例如,我使用的是一个非自己编写的UI库,它是单独编译的,我正在添加它.其中一些添加使用单体,这些单体也在我的.a库中使用.
单独的编译会导致这种情况吗?别的什么?
我设法解决这个问题的唯一方法是在main.cpp文件中创建一个全局对象,我用我需要的任何单例初始化它.然后,所有代码都通过以下调用访问此公共全局对象:
GlobalObject::getSomeClass().doSomething()
我不想每次创建另一个单例时都要为这个对象添加一个额外的方法.使用第一种访问方法,语法似乎更清晰,更熟悉:
SomeClass::getInstance().doSomething();
如果您有任何想法,意见等,请告诉我.
谢谢.
您的问题是您的模板将在多个编译单元中实例化,因为它完全是内联的.因此,在每个使用该模板的编译单元中,您最终将创建一个单例(每个编译单元).您需要的是强制全局链接,以便所有编译单元引用相同的模板实例.即将推出的C标准将通过 extern template支持此功能.您现在可以做的是禁用项目中的自动实例化并手动实例化您明确使用的模板.这样,当您在任何编译单元中使用模板时,您将生成对实现的未知引用,然后链接器可以从(一个)编译单元中执行显式实例化.