类扩展模板类的C ++符号导出

时间:2011-06-17 00:57:26

标签: c++ templates visual-c++ linker

我正在开发一个使用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”项目中消失。如果我删除模板部分(它在我的例子中并不是真的有用,但在现实生活中它是这样的),一切都很好。

如果函数没有被使用或类似的东西,它看起来好像没有被编译。有什么想法吗?

提前致谢。

3 个答案:

答案 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>;