我有一个模板单例类,带有一个静态实例和一个静态getInstance()方法。但是,我在g++(MinGW)实例上收到 undefined reference 错误;起初,我以为是链接器顺序错误,但是无论我按什么顺序放置它们,我都会得到相同的结果。
但是,我发现,如果我明确地专门化了实例,它将进行编译(这不是可接受的解决方案)。所以,这是代码:
Singleton.hpp:
#ifndef SINGLETON_HPP
#define SINGLETON_HPP
#include <iostream>
template<int X=100>
class Singleton {
protected:
static Singleton<X> *instance;
public:
static Singleton<X>& getInstance() {
if(!Singleton<X>::instance) {
Singleton<X>::instance = new Singleton<X>();
}
return *Singleton<X>::instance;
}
void foo() {
std::cout << "Test<" << X << ")::foo()" << std::endl;
}
};
#endif
Singleton.cpp:
#include "Singleton.hpp"
template<int X>
Singleton<X>* Singleton<X>::instance = NULL;
#ifdef SPECIALIZE
template<>
Singleton<100>* Singleton<100>::instance = NULL;
#endif
Main.cpp:
#include "Singleton.hpp"
int main(int ac, char *av[]) {
Singleton<100> &sing = Singleton<100>::getInstance();
sing.foo();
}
然后是三种不同的编译方式以及输出:
没有专长,SingletonMain.o首先链接:
C:\Test>g++ -c Singleton.cpp
C:\Test>g++ -c SingletonMain.cpp
C:\Test>g++ -o Singleton.exe SingletonMain.o Singleton.o
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x7): undefined reference to `Singleton<100>::instance'
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x1c): undefined reference to `Singleton<100>::instance'
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x21): undefined reference to `Singleton<100>::instance'
collect2: ld returned 1 exit status
没有专长,Singleton.o首先链接:
C:\Test>g++ -c Singleton.cpp
C:\Test>g++ -c SingletonMain.cpp
C:\Test>g++ -o Singleton.exe Singleton.o SingletonMain.o
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x7): undefined reference to `Singleton<100>::instance'
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x1c): undefined reference to `Singleton<100>::instance'
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x21): undefined reference to `Singleton<100>::instance'
collect2: ld returned 1 exit status
特化:
C:\Test>g++ -DSPECIALIZE -c Singleton.cpp
C:\Test>g++ -DSPECIALIZE -c SingletonMain.cpp
C:\Test>g++ -DSPECIALIZE -o Singleton.exe Singleton.o SingletonMain.o
现在,这里似乎确实有人遇到类似的问题-C++ template static member instantiation-但“解决方案”是为您可能使用的每种类型都明确地专门化……这似乎完全违背了模板的目的……所以必须有更好的方法,对吗?
最佳答案
您必须将静态成员定义移动到标题。就像其他所有模板化的一样,类模板的静态成员的定义必须在使用该模板的每个翻译单元中都存在。这基本上意味着它属于标题。
引用C++ 11,[temp]§6
:
(强调我的)