C++ 如何在stl模板中使用导出的类(uu declspec(dllexport))?
我使用的是导出类C++ 如何在stl模板中使用导出的类(uu declspec(dllexport))?,c++,templates,dllexport,C++,Templates,Dllexport,我使用的是导出类 class __declspec(dllexport) myclass { private: template __declspec(dllexport) class std::map<myclass*,int>; std::map<myclass*,int>m_map; //something }; class\uuu declspec(dllexport)myclass { 私人: 模板declspec(dl
class __declspec(dllexport) myclass
{
private:
template __declspec(dllexport) class std::map<myclass*,int>;
std::map<myclass*,int>m_map;
//something
};
class\uuu declspec(dllexport)myclass
{
私人:
模板declspec(dllexport)类std::map;
std::mapm_图;
//某物
};
当我这样做时,我得到一个警告C4251,说m_map:类'std::map'需要有dll接口才能被类myclass的客户端使用。关于如何解决这个问题,有什么想法吗?
Atul不能导出包含未导出成员的类。一个可能的解决方案是使用Pimpl习惯用法。使用Pimpl,用户不知道类的成员。因此,不需要导出stl类。有关pimpl的更多信息,请查看以下内容: 或 例如: 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;
};
类myclassImpl{
私人:
std::mapm_图;
};
您不应该在使用DLL的代码将要使用的头文件中使用u declspec(dllexport),因为它们需要使用u 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模板;
在包含的标题中。注意这里的外部。
在一个编译单元内声明相同但没有外部和FOO_API,因此:
template class Templ<MyClass, int >;
模板类模板;
这意味着使用库的代码不会实例化模板,而是使用库中的模板。当模板具有虚拟成员时,这尤其有用
如果模板来自标准库或boost,则使用您的代码的版本必须与您的版本相同,否则可能会出现严重问题
在您自己的示例中,它出现在私有区域,这表明您希望从库的接口中重构它。理想情况下,库应该只公开公共方法和成员,而不是转发声明。为了使类不可复制和不可分配,可以使用私有复制构造函数和赋值-它们实际上不是实现的一部分,它们是类接口的一部分(您是说您不能复制或赋值)。@David,你能详细说明一下这个Pimpl习惯用法吗?很好,但是你让析构函数虚拟化会给你自己带来更多的问题。没有人会从它们中派生出来,因为如果你想要多态性,你就把它放到pImpl中。您还应该使您的类不可复制和不可分配。@CashCow您是对的-代码没有适当注意分配和复制。但它可以被库的用户继承。这就是我在2010年时的做法,但现在实际上我有一个stdafx.h文件或类似文件,它包含在所有项目源中,但不包含在外部用户源中,它定义了FOO_API或任何东西。然后,标头只执行#ifndef FOO#u API,还将执行#pragma命令库。