如何在DLL中实现类计数器? [英] How to implement a class counter in DLL?

查看:250
本文介绍了如何在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屋!

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