这不是一个突破性的问题,但我喜欢从警告中清除我的代码,所以这让我很紧张。
我一直在使用cmpl 11版本的pimpl成语以通常的方式隐藏我的库的类实现。
// dll header
class FrameworkImpl;
class EXPORT_API Framework
{
Framework(const Framework&) = delete;
Framework& operator=(const Framework&) = delete;
Framework(Framework&&) = delete;
Framework& operator=(Framework&&) = delete;
public:
Framework();
~Framework();
private:
std::unique_ptr<FrameworkImpl> impl_;
};
// application implementation
int main()
{
std::unique_ptr<Framework> test = std::make_unique<Framework>();
}
一切都会好的,但我会继续收到警告:
warning C4251: 'Framework::impl_': class 'std::unique_ptr<FrameworkImpl,std::default_delete<_Ty>>' needs to have dll-interface to be used by clients of class 'Framework'
所以我试着添加:
template class EXPORT_API std::unique_ptr<FrameworkImpl>;
在前方声明之前,警告只会改为:
warning C4251: 'std::_Unique_ptr_base<_Ty,_Dx>::_Mypair': class 'std::_Compressed_pair<_Dx,FrameworkImpl *,true>' needs to have dll-interface to be used by clients of class 'std::_Unique_ptr_base<_Ty,_Dx>'
自VS2010以来,我一直在看这个问题,我无法找到解决这个问题的好方法。在gcc或clang上没有问题,使用旧的原始指针版本会让我心碎。
答案 0 :(得分:13)
这是DLL类的一个非常常见的问题,它使用std
中的模板。
为什么会这样?
原因非常简单:标准仅指定保证,限制和要求。所以你可以肯定的是,每个C ++ 11编译器都会提供std::unique_ptr
,其外观和工作方式如on this page所述。但其他一切都依赖于实现。
主要问题是,不同的实现可能(通常会)对特定类型使用完全不同的结构。它们使用其他辅助变量,不同的布局等。即使在同一编译器的两个版本之间,这可能也不同。因此,如果客户端代码以任何方式触及类的成员变量,则需要为它们提供DLL接口。这适用于dllexport
ed class使用的所有类型的递归。
您可能需要阅读this article on MSDN,其中介绍了容器的这个问题。
此问题可以简化为以下内容:
dllexport
或使用dllexport
方法使用其他间接。进一步阅读:
答案 1 :(得分:6)
您可以只导出公共方法,而不是导出整个类:
class Framework
{
Framework(const Framework&) = delete;
Framework& operator=(const Framework&) = delete;
Framework(Framework&&) = delete;
Framework& operator=(Framework&&) = delete;
public:
EXPORT_API Framework();
EXPORT_API ~Framework();
private:
std::unique_ptr<FrameworkImpl> impl_;
};
答案 2 :(得分:1)
解决方案是在impl声明和Olga Perederieieva答案的组合之后声明构造函数/析构函数
有关详细说明和示例,请参阅此website
标题:
#include <memory>
class FridgeImpl;
class Fridge
{
public:
DLL_EXPORT Fridge();
DLL_EXPORT ~Fridge();
DLL_EXPORT void coolDown();
private:
std::unique_ptr<FridgeImpl> impl_;
};
实施:
#include "Engine.h"
#include "Fridge.h"
class FridgeImpl
{
public:
void coolDown()
{
/* ... */
}
private:
Engine engine_;
};
Fridge::Fridge() : impl_(new FridgeImpl) {}
Fridge::~Fridge() = default;