如何在DLL中实现类计数器? [英] How to implement a class counter in DLL?
问题描述
到目前为止,我有:
// TypeCounter.h
template <typename Base>
class Counter : public Base
{
protected:
static int typeIndexCounter;
};
template <typename T, typename Base>
class Bridge : public Counter<Base>
{
public:
virtual ~Bridge() {}
virtual int GetTypeIndex() const
{
return TypeIndex();
}
static int TypeIndex()
{
static int typeIndex = typeIndexCounter++;
return typeIndex;
}
};
// static variable definition
template <typename Base>
int Counter<Base>::typeIndexCounter;
用例如:
class SBase
{ ... }
class S0 : public Bridge<S0, SBase>
{ ... }
class S1 : public Bridge<S1, SBase>
{ ... }
class S2 : public Bridge<S2, SBase>
{ ... }
所以对于每种 Base
class,我可以算出它有多少派生(如果已经被实例化了,当然)。
So for each kind of Base
class, I can count how many derives it has (if it has ever been instantiated, of course).
问题是,这个计数器
类在一个DLL中。
The problem is that, this Counter
class is in a DLL.
如果我有这个DLL的多个用户,那么每个用户将实例化它自己的桥梁
和计数器
,然后 TypeIndex()
在这些用户中,对于相同的 T
。
If I have multiple users of this DLL, then each user would instantiate its own Bridge
and Counter
, then the TypeIndex()
can be different among these users for the same T
.
我尝试将 __ declspec在
,但是在用户端有编译错误通过定义一个宏,用户端会将 Counter
和 Bridge
之前, export
更改为 import
。
尽管错误,它也是一个错误的方法,因为不应该导出类模板。
I tried to put __declspec(dllexport)
before Counter
and Bridge
, but there are compile errors on the user side (the user side would change export
to import
, by defining a macro).
Despite the errors, it is also a wrong approach, since one should not export class template.
所以我想确保 TypeIndex ()
对于某些 T
保持不变,即使这样e是相同的 T
的许多实例,如何实现?
So I want to make sure that the TypeIndex()
keep the same for certain T
, even if there are many instantiations for the same T
, how can I achieve this?
谢谢! / p>
Thanks!
推荐答案
确实,您无法导出类模板。这是没有用的,因为你有所有的类模板写在头文件中,所以实际上不需要导出才能使用代码。
相反,您必须导出类实例化,然后使用extern关键字:
It is true that you cannot export a class template. This is even useless, since you have all the class template written in the header file, so no export is actually required to be able to use the code. Instead, you have to export the class instantiation, and later use it with the "extern" keyword:
这是编译库时的头文件:
This is the header file when compiling the library:
class SBase{ ... }
template class __declspec(dllexport) Bridge<S0, SBase>;
class S0 : public Bridge<S0, SBase>
{ ... }
template class __declspec(dllexport) Bridge<S1, SBase>;
class S1 : public Bridge<S1, SBase>
{ ... }
template class __declspec(dllexport) Bridge<S2, SBase>;
class S2 : public Bridge<S2, SBase>
{ ... }
这是构建客户端代码时的头文件:
And this is the header file when building the client code:
class SBase{ ... }
extern template class __declspec(dllimport) Bridge<S0, SBase>;
class S0 : public Bridge<S0, SBase>
{ ... }
extern template class __declspec(dllimport) Bridge<S1, SBase>;
class S1 : public Bridge<S1, SBase>
{ ... }
extern template class __declspec(dllimport) Bridge<S2, SBase>;
class S2 : public Bridge<S2, SBase>
{ ... }
所以现在,链接器将通过所有您的程序,不仅在您的编译模块。
So now, the linker will search for this classes through all your program, not only in your compiling module.
这应该是typedefed,以获得不同的输出使用相同的代码:
This should be typedefed, in order to get the different outputs using the same code:
#ifdef LIBRARY_BUILD
#define EXPORT __declspec(dllexport)
#define TEMPLATE_EXPORT
#else
#define EXPORT __declspec(dllimport)
#define TEMPLATE_EXPORT extern
#endif
class SBase{ ... }
TEMPLATE_EXPORT template class EXPORT Bridge<S0, SBase>;
class S0 : public Bridge<S0, SBase>
{ ... }
TEMPLATE_EXPORT template class EXPORT Bridge<S1, SBase>;
class S1 : public Bridge<S1, SBase>
{ ... }
TEMPLATE_EXPORT template class EXPORT Bridge<S2, SBase>;
class S2 : public Bridge<S2, SBase>
{ ... }
必须在具有静态成员的所有模板类中完成,所以所有的模板类只有一个实例化的成员,而不是每个编译模块。
This have to be done in ALL template classes with static members, so all the template classes have got only ONE instantiation of the members, instead of one per compilation module.
您可以在这里获得更多信息:
共享库中的类和静态变量
You can have further information here: classes and static variables in shared libraries
编辑:
重新阅读你的问题,我会声明为extern你的模板基类(因为它是一个静态成员),而不是特定的:
Re-reading your question, I would declare as extern your template base class (since it is the one with the static member), not the particular ones:
TEMPLATE_EXPORT template class EXPORT Counter<SBase>;
所以现在,你可以有任何SBase的派生类,所有的都将依赖于相同的Counter类,而不需要声明自己为外部人。
当然,如果SBase在某个库中,那么它应该也被声明为extern(通常的方式,只是__declspec(dllexport),因为它不是一个模板)。
So now, you can have any SBase's derived class and all will be relying on the same Counter class, without the need to declare themselves as extern. Of course, if SBase is in some library, it should be declared also itself as extern (in the normal way, just __declspec(dllexport), since it is not a template).
这篇关于如何在DLL中实现类计数器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!