DLL 导出模板基类的静态成员 [英] DLL-Exporting static members of template base class

查看:39
本文介绍了DLL 导出模板基类的静态成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Within a DLL I have an exported non-template class with a template base class. This template base class has a static member variable. I use the static base member in an executable that links to the DLL with the exported non-template class.

在许多情况下,我会收到未解决的外部符号或有关不一致链接的投诉.我发现了一种可行的方案,但它似乎很笨拙,所以我想知道是否有更好的方法,以及这种更好的方法是否也可能指向 VS2010 SP1 的 C++ 编译器/链接器的缺陷.

In many scenarios I get unresolved external symbols or complaints about inconsistent linkage. I have found one scenario that works, but it seems to be kludgey so I'm wondering if there is a better way and if that better way might also point to deficiencies in VS2010 SP1's C++ compiler/linker.

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

This is the minimal scenario of the DLL that I could distill - I don't think I could remove anything here without breaking the scenario.

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

然后是DLL的用户

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

推荐答案

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

In C++ generally, when a plain class has a static member, it should be declared in the header, but instantiated in a source file. To do otherwise would cause too many instances of the static class member to be created.

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

Templates are kind of the same way, except the compiler has some magic for templates that it doesn't have for non-templates. Specifically, it magically eliminates duplicate instances of a template instantiation during the linking phase of a build.

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

This is the source of your problem: The stuff inside the _MYDLL portion is automatically instantiated by every source file that includes this template and also makes TBaseClass objects. Then the linker automatically eliminates duplicates.

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

Trouble is, you have two links: the DLL link and the client link. Both will make TBaseClass instantiations, and both will make those g_initial_value objects.

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

To solve this: Move the stuff in the _MYDLL conditional into the CPP file, so the client won't get instructions to build the instance itself.

这篇关于DLL 导出模板基类的静态成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆