DLL-导出模板基类的静态成员

Jor*_*ans 9 c++ windows templates visual-studio-2010

在DLL中,我有一个带有模板基类的导出的非模板类.此模板基类具有静态成员变量.我在可执行文件中使用静态基本成员,该可执行文件使用导出的非模板类链接到DLL.

在许多情况下,我得到了未解决的外部符号或关于不一致链接的抱怨.我发现一个有效的方案,但它似乎是kludgey所以我想知道是否有更好的方法,如果更好的方式也可能指向VS2010 SP1的C++编译器/链接器的缺陷.

这是我可以提炼的DLL的最小场景 - 我不认为我可以在不破坏场景的情况下删除任何内容.

// Header file
template<typename T>
class _MYDLL_EXPORTS TBaseClass
  {
  public:
    static const double g_initial_value;
  };

class _MYDLL_EXPORTS MyClass : public TBaseClass<MyClass>
  {    
  };

// Kludge: use this code only when building the DLL, not when including
// from the DLL's client
#ifdef _MYDLL
  template<typename T>
  const double TBaseClass<T>::g_initial_value = 1e-5;
#endif


// CPP file
#include "header.h"
// Explicit instantiation of the template for the correct parameter.
template class TBaseClass<MyClass>;
Run Code Online (Sandbox Code Playgroud)

然后是DLL的用户

#include <header.h>  
#include <iostream>
int main(void) {
 MyClass c;
 std::cout << c.g_initial_value;
return 0;
}
Run Code Online (Sandbox Code Playgroud)

Ala*_*jeu 6

通常在 C++ 中,当一个普通类有一个静态成员时,它应该在头文件中声明,但在源文件中实例化。否则会导致创建过多的静态类成员实例。

模板有点类似,除了编译器对模板有一些魔法,而对于非模板则没有。具体来说,它在构建的链接阶段神奇地消除了模板实例化的重复实例。

这是您的问题的根源:_MYDLL 部分中的内容由包含此模板的每个源文件自动实例化,并且还生成 TBaseClass 对象。然后链接器会自动消除重复项。

问题是,您有两个链接:DLL 链接和客户端链接。两者都会创建 TBaseClass 实例化,并且都会创建那些 g_initial_value 对象。

要解决这个问题:将 _MYDLL 条件中的内容移动到 CPP 文件中,这样客户端就不会得到构建实例本身的指令。