Templates 如何在C++中处理不同OSs中的模板类的静态属性?

Templates 如何在C++中处理不同OSs中的模板类的静态属性?,templates,c++11,static,linker,Templates,C++11,Static,Linker,这是一个相当技术性的问题,因为我在windows上遇到了一个模板类的静态属性问题 比如说: A.h C0.cpp B * b = B::get(); C1.cpp B * b = B::get(); OK,到目前为止很简单,但是说我们编译模块:链接器是否自动地认为B::OBJ在Ma.O,C1.O和C0.O*中是完全相同的。o是对象文件,不一定来自gcc 如果没有,如何做到这一点 然后,考虑我们首先在外部DLL LBC.SO或LBC.A/LBC.LIb+C.DLL编译C1.CPP和C0.CP

这是一个相当技术性的问题,因为我在windows上遇到了一个模板类的静态属性问题

比如说:

A.h

C0.cpp

B * b = B::get();
C1.cpp

B * b = B::get();

OK,到目前为止很简单,但是说我们编译模块:链接器是否自动地认为B::OBJ在Ma.O,C1.O和C0.O*中是完全相同的。o是对象文件,不一定来自gcc 如果没有,如何做到这一点

然后,考虑我们首先在外部DLL LBC.SO或LBC.A/LBC.LIb+C.DLL编译C1.CPP和C0.CPP,这取决于编译器/操作系统,然后是可执行文件,它与C.DLL/SO连接。B::obj呢?它应该同时存在于lib和exe中。。。 如何使它指定相同的东西?或者如果是这种情况,系统如何处理? 我们还可以假设有许多库使用这个符号作为静态或动态插件

实际上,我问这些问题是因为在linux上,当我编译一个这样的应用程序时,符号被正确解析,并且只有一个B::obj实例。
但是现在我正在用mingw编译相同的代码,并且来自不同库的init之后的get没有传递assert,我得出结论,每个库有一个实例…

不仅仅是模板。每当在DLL中使用静态变量时,它都会在DLL中使用该静态变量的副本。在EXE中使用相同变量时,在EXE中使用副本。对DLL中副本的更改不会反映在EXE使用的副本中,反之亦然

通过一些困难或使用适当的第三方库,您可以创建一个单例模式,以便DLL和EXE使用同一个单例实例。然后,您可以将原本是静态的变量放入单例中。您的模板类A可以使用单例类来存储obj,如果需要,您可以在其他地方使用其他单例类


或者,您可以重新设计模板,使obj不是静态的。

我也在四处搜索相同的问题。下面是我当前的解决方案,使用c++11显式实例化声明:

// B.h
class B;
// explicit instantiation declaration 
extern template class A<B>;
class B: public A<B> {
    //...
};
并添加一个B.cpp

// B.cpp
// explicit instantiation definition 
template class A<B>;
现在,对于main.cpp、C0.cpp和C1.cpp,它们都包括B.h,不会为A生成代码,而是使用在B.cpp中生成的唯一代码


PS:我不确定使用“外部模板”是否正确,因为它似乎主要用于减少编译时间。

对不起,我忘记了A.h中的两行,因为实际上,A是我应用程序中的单例类。。。问题是如何创建这样一个单例类,用户不需要定义::obj,但很抱歉,有另一个复制失败,并且obj的声明不存在。正如您所发现的,当您链接DLL时,很难在Windows中滚动您自己的单例类。我甚至不会在自己的软件中尝试。相反,我成功地使用了ACE提供的单例模式。我相信还有其他第三方软件包可以做到这一点。
B * b = B::get();
// B.h
class B;
// explicit instantiation declaration 
extern template class A<B>;
class B: public A<B> {
    //...
};
// B.cpp
// explicit instantiation definition 
template class A<B>;