如何在 stl 模板中使用导出的类 (__declspec(dllexport))?
Posted
技术标签:
【中文标题】如何在 stl 模板中使用导出的类 (__declspec(dllexport))?【英文标题】:how to use an exported class (__declspec(dllexport))in an stl template? 【发布时间】:2010-11-23 06:47:01 【问题描述】:我正在使用导出的类
class __declspec(dllexport) myclass
private:
template __declspec(dllexport) class std::map<myclass*,int>;
std::map<myclass*,int>m_map;
//something
;
当我这样做时,我收到一条警告 C4251,说 m_map:class 'std::map<_kty>' 需要有 dll 接口供 myclass 类的客户端使用。 关于如何解决这个问题的任何想法? 阿图尔
【问题讨论】:
【参考方案1】:您不应该在使用 DLL 的代码将使用的头文件中使用 __declspec(dllexport),因为它们需要使用 __declspec(dllimport)。
因此,如果设置了特定的其他定义,您应该创建一个使用 dllexport 的宏,如果没有设置,则使用 dllimport。
在某处的通用标题中:
#ifdef EXPORTING_FOO
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif
你可以实例化一个模板:
extern template class FOO_API Templ<MyClass, int >;
在包含的标题中。注意这里的外部。 在一个编译单元内声明相同但没有 extern 和 FOO_API,因此:
template class Templ<MyClass, int >;
这意味着使用您的库的代码不会实例化模板,而是使用您库中的模板。这在模板具有虚拟成员时特别有用。
如果模板来自标准库或 boost,则使用您的代码必须使用与您相同的版本,否则可能会出现严重问题。
鉴于在您自己的示例中,它出现在私有区域中,这表明您希望将其从库的界面中重构出来。理想情况下,您的库应该只公开除前向声明之外的公共方法和成员。私有复制构造函数和分配以使类不可复制和不可分配很好-它们实际上并不是实现的一部分,它们是您的类接口的一部分(您是说您不能复制或分配它们)。
【讨论】:
这就是我在 2010 年以前的做法,但现在实际上我有一个 stdafx.h 文件或类似文件,它包含在所有项目源中,但不包含在外部用户源中,它定义了 FOO_API 或其他.然后,标头会简单地执行 #ifndef FOO_API 并且也会执行 #pragma 注释库。【参考方案2】:您不能导出具有未导出成员的类。一个可能的解决方案是使用 Pimpl 成语。使用 Pimpl,用户不知道该类的成员。所以不需要导出 stl 类。有关 pimpl 的进一步阅读,请检查以下内容: http://c2.com/cgi/wiki?PimplIdiom 或 http://www.gamedev.net/reference/articles/article1794.asp
例子:
myclass.h:
class __declspec(dllexport) myclass
public:
myclass();
virtual ~myclass();
private:
myclass(const myclass& other)
myclass& operator=(const myclass& rhs) return *this;
myclassImpl* m_Pimpl;
;
myclass.cpp:
#include "myclass.h"
#include "myclassImpl.h"
myclass::myclass()
:m_Pimpl(new myclassImpl())
myclass::~myclass()
delete m_Pimpl;
myclassImpl.h:
class myclassImpl
private:
std::map<myclass*,int>m_map;
;
【讨论】:
@David,你能详细说明一下这个 Pimpl 成语吗? 很好,但是你给自己造成了更多的问题,使析构函数虚拟化。没有人会从它们中派生出来,因为如果你想要多态性,你就把它放到 pImpl 中。您还应该使您的课程不可复制且不可分配。 @CashCow 你是对的 - 代码没有妥善处理分配和复制。但它可以由库的用户继承。以上是关于如何在 stl 模板中使用导出的类 (__declspec(dllexport))?的主要内容,如果未能解决你的问题,请参考以下文章