我正在开发一个使用Visual Studio 2008构建的C ++项目。 我正在定义(在一个生成一个dll的项目中)一个模板类和一个派生的非模板,一个:
template <class T>
struct DLL_EXPORT Base {
int base() { return 1; }
};
struct DLL_EXPORT Deriv: public Base<Deriv> {
int deriv() { return 1; }
};
DLL_EXPORT
是常见的东西:
#ifdef COMPILING_MY_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
现在,当我尝试在另一个项目中使用我的Deriv
课程时,问题就出现了。如果我只使用Deriv
中的函数,则效果很好:
Deriv d;
d.deriv();
但是如果我尝试调用d.base()
,我会收到以下链接器错误:
error LNK2019: unresolved external symbol "__declspec(dllimport) public: int __thiscall Base<struct Deriv>::base(void)" (__imp_?base@?$Base@UDeriv@@@@QAEHXZ)
如果在我的dll代码的其他地方,我正在使用d.base()函数,它运行良好,并且链接器错误在“user”项目中消失。如果我删除模板部分(它在我的例子中并不是真的有用,但在现实生活中它是这样的),一切都很好。
如果函数没有被使用或类似的东西,它看起来好像没有被编译。有什么想法吗?
提前致谢。
答案 0 :(得分:3)
如果这是您的问题,您可以通过explicitly instantiating the template修复此问题。
在DLL中的一个.cc文件(不是头文件)中,包含您的模板定义并写入:
template int Base<Deriv>::base();
这应该强制编译器将Base<Deriv>::base()
的代码放入该编译单元,以便链接器可以找到它。
答案 1 :(得分:3)
不要在模板定义上使用__declspec(dllexport),因为它们不会被导出(在实例化之前它们不是真正的代码)。 它们仅在头文件中供源使用。您可以在模板的特化上使用__declspec(dllexport),但必须在DLL中至少对其进行一次实例化。
答案 2 :(得分:2)
我对此并不了解,但我认为您可以通过编写
来解决这个问题template struct Base<Derive>;
源文件中的某个位置。 (或者template DLL_EXPORT struct Base<Derive>;
)