我目前正在开发一个大量使用Singletons和动态库的应用程序(使用dlopen) 我的问题是我的单例在应用程序和动态库中的实例是不同的(即在我的实现中,Singleton :: getInstance方法返回不同的地址)
这就是我定义Singleton的方法
// Singleton.hpp
template<typename T>
class Singleton
{
static T *_instance;
protected:
Singleton<T>() {}
virtual ~Singleton<T>() {}
public:
static T *getInstance() {
if (_instance == NULL)
_instance = new T;
return (_instance);
}
static void deleteInstance() {
if (_instance) {
delete _instance;
_instance = NULL;
}
}
};
template<typename T>
T *Singleton<T>::_instance = NULL;
然后,如果我想让一个类Test成为Singleton,我需要这样做:
// Test.hh
#include "Singleton.hpp"
class Test : public Singleton<Test>
{
friend class Singleton<Test>;
private:
Test();
public:
virtual ~Test();
void doSomeStuff();
};
现在,如果我想使用Test,我会这样做:
#include "Test.hh"
int main() {
Test *test = Test::getInstance();
test->doSomeStuff();
return (0);
}
为了解决这个问题,我尝试以某种方式“extern”(使用关键字)静态类成员Singleton :: _ instance,但我从未成功编译我的应用程序...... GCC拒绝那种代码(在Singleton中) .hpp)文件:
template<typename T>
extern T *Singleton<T>::_instance;
答案 0 :(得分:1)
以下需要移出singleton.hpp。如上所述,它为每个.cpp文件创建一个指针实例,包括singleton.hpp。
template<typename T>
T *Singleton<T>::_instance = NULL;
请记住,这是一个定义,而不是声明。因此,包含头部的每个目标文件现在都定义了Singleton :: _ instance。如果多个.cpp文件包含singleton.h并在单个目标(可执行文件或库)中实例化具有相同类型的模板,则将获得多个定义的符号。
要使此代码更正,您需要选择单个.cpp文件(在单例模板的客户端中)并在那里定义_instance。这显然不是非常理想的,所以请考虑不使用单例(您的第一个,最佳选项)或使用不同的单例模式。