4

我正在使用导出的类

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,_Ty>' 需要有 dll 接口供 myclass 类的客户端使用。
关于我如何解决这个问题的任何想法?
阿图尔

4

2 回答 2

6

您不应该在使用 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-11-23T09:55:23.207 回答
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;
};

我的类.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;
};
于 2010-11-23T07:15:39.467 回答