2009-06-20 78 views
31

我想链接到一个模板类的共享库,但它给我“未定义的符号”错误。我将问题简化为约20行代码。C++共享库模板:未定义的符号错误

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; 
} 

这是我编的lib郭宝宏:

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中,并且不链接到共享库,则一切正常。

如何,我可以得到一个模板类,像这样通过一个共享库的工作?

我使用的MacOS 10.5 GCC 4.0.1。

+0

Duplicate:http://stackoverflow.com/questions/999358/undefined-symbols-linker-error-with-simple-template-class/999383#999383 – 2009-06-20 21:48:21

回答

34

除了其他答案,您可以显式实例化模板类。这只有在事先知道模板参数可能呈现的类型时才有用。您可以使用库中的所有这些类型实例化模板。

对于你的榜样编译,只需添加以下shared.cpp结束:

// Instantiate myclass for the supported template type parameters 
template class myclass<int>; 
template class myclass<long>; 

此实例与类型= INT模板,并将实例化代码的共享库。为您需要的所有类型添加尽可能多的显式实例。

同样,如果你希望能够与任意类型的参数来实例化的模板,然后你必须的定义添加到头文件,以便在实例化时,编译器知道模板的源代码其他编制单位。

16

模板函数定义必须驻留在头文件中。将来自shared.cpp的定义移至shared.h。

所以,你不能编译这一个共享库,然后链接到它。它只是不能这样工作。

+2

因此,使用模板共享库是不可能的? – nolk 2009-06-20 22:00:35

+2

恰恰相反,这很容易。把它放在一个头文件中,并分享它。你甚至不需要编译器;)模板在被实例化之前不会被编译,所以如果你将一个模板放在一个.cpp文件中,并且将它作为共享库编译,模板代码就会被简单地删除。模板定义必须对用户可见。 – jalf 2009-06-20 22:23:49

5

您需要在头文件的模板类的实现也是如此。这是C++中模板的约束。因此,无论从包括主(#包括)shared.cpp或刚刚从shared.cpp移动代码shared.h

1

编译器必须看到所有的代码模板,所以它可以产生的相应的代码您想要使用的实际类型。 所以你应该把所有的代码放在你的.h中。文件。