我正在尝试使用模板类链接到共享库,但它给了我“未定义的符号”错误。我已经将问题浓缩为大约20行代码。
shared.h
template <class Type> class myclass {
Type x;
public:
myclass() { x=0; }
void setx(Type y);
Type getx();
};
shared.cpp
#include "shared.h"
template <class Type> void myclass<Type>::setx(Type y) { x = y; }
template <class Type> Type myclass<Type>::getx() { return x; }
的main.cpp
#include <iostream>
#include "shared.h"
using namespace std;
int main(int argc, char *argv[]) {
myclass<int> m;
cout << m.getx() << endl;
m.setx(10);
cout << m.getx() << endl;
return 0;
}
这是我编译库的方式:
g++ -fPIC -c shared.cpp -o shared.o
g++ -dynamiclib -Wl,-dylib_install_name -Wl,libshared.dylib -o libshared.dylib shared.o
主程序:
g++ -c main.cpp
g++ -o main main.o -L. -lshared
仅出现以下错误:
Undefined symbols:
"myclass<int>::getx()", referenced from:
_main in main.o
_main in main.o
"myclass<int>::setx(int)", referenced from:
_main in main.o
如果我删除shared.h/cpp
中的'模板'内容,并用'int'替换它们,一切正常。另外,如果我只是将模板类代码复制并粘贴到main.cpp
中,并且不链接到共享库,那么一切都可以正常工作。
如何通过共享库获取这样的模板类?
我正在使用带有GCC 4.0.1的MacOS 10.5。
答案 0 :(得分:40)
除了其他答案,您还可以显式实例化模板类。这只有在事先知道模板参数可以采用的类型时才有用。您可以在库中实例化所有这些类型的模板。
要编译示例,只需将以下内容添加到 shared.cpp 的末尾:
// Instantiate myclass for the supported template type parameters
template class myclass<int>;
template class myclass<long>;
使用Type = int实例化模板,并将实例化的代码放在共享库中。为您需要的所有类型添加尽可能多的显式实例化。
同样,如果您希望能够使用任意Type参数实例化模板,那么必须将定义添加到头文件中,以便编译器知道模板的源代码在其他编译单元中实例化时。
答案 1 :(得分:18)
模板函数定义必须位于头文件中。将定义从shared.cpp移动到shared.h。
因此,您无法将其编译为共享库,然后链接到它。它只是不起作用。
答案 2 :(得分:6)
您还需要在头文件中包含模板类的实现。这是C ++中模板的约束。因此要么包含main(#include)中的shared.cpp,要么只从shared.h中的shared.cpp中移动代码
答案 3 :(得分:2)
编译器必须查看模板的所有代码,因此它可以为您要使用的实际类型生成相应的代码。 因此,您应该将所有代码放在.h中。文件。