首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >dll中的std::unique_ptr pimpl使用visual studio生成C4251。

dll中的std::unique_ptr pimpl使用visual studio生成C4251。
EN

Stack Overflow用户
提问于 2015-08-19 14:14:15
回答 3查看 5.8K关注 0票数 22

这不是一个打破的问题,但我喜欢清理我的代码从警告,所以这是我的神经。

我一直在使用pimpl成语的c++11版本来用通常的方式隐藏库的类实现。

代码语言:javascript
运行
复制
// 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>();
}

一切都会好起来的,但我会一直收到警告:

代码语言:javascript
运行
复制
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'

所以我试着说:

代码语言:javascript
运行
复制
template class EXPORT_API std::unique_ptr<FrameworkImpl>;

在前向声明之前,但警告将更改为:

代码语言:javascript
运行
复制
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或嘎嘎没有问题,使用旧的原始指针版本会让我心碎。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-01-03 18:15:40

解决方案是在impl声明之后声明构造函数/析构函数以及Olga Perederieieva答案的组合。

有关详细说明和示例,请参阅此网站

标题:

代码语言:javascript
运行
复制
#include <memory>

class FridgeImpl;

class Fridge
{
public:
   DLL_EXPORT Fridge();
   DLL_EXPORT ~Fridge();
   DLL_EXPORT void coolDown();
private:
   std::unique_ptr<FridgeImpl> impl_;
};

执行情况:

代码语言:javascript
运行
复制
#include "Engine.h"
#include "Fridge.h"

class FridgeImpl
{
public:
   void coolDown()
   {
      /* ... */
   }
private:
   Engine engine_;
};

Fridge::Fridge() : impl_(new FridgeImpl) {}

Fridge::~Fridge() = default;
票数 1
EN

Stack Overflow用户

发布于 2015-08-19 14:40:36

这对于使用std模板的DLL类来说是一个非常常见的问题。

为什么会发生这种事?

原因很简单:标准只规定保证、限制和要求。因此,您可以确定,每个C++ 11编译器都将提供std::unique_ptr,其外观和工作方式与所描述的在这页上相同。但其他一切都依赖于实现。

主要问题是,不同的实现可能(而且通常也会)对特定类型使用完全不同的结构。它们使用额外的辅助变量、不同的布局等等。即使在同一编译器的两个版本之间,这也可能有所不同。因此,如果客户端代码以任何方式接触到类的成员变量,则需要为它们提供DLL接口。它递归地应用于dllexported类使用的所有类型。

您可能想要阅读本文是关于MSDN的,这说明了容器中的这个问题。

这个问题可以简化为以下几个方面:

  • 如果客户端代码无法访问您的数据,请禁用此警告。
  • 如果您有要由客户端代码使用的成员,则创建包装器,即dllexported或使用dllexported方法的附加间接方向。
  • 通常,您可以使用PIMPL隐藏非DLL类型,但在您的情况下它是不适用的,因为您使用不可导出类型来实际实现PIMPL。

进一步读:

票数 17
EN

Stack Overflow用户

发布于 2017-06-08 23:34:29

与导出整个类不同,您只能导出公共方法:

代码语言:javascript
运行
复制
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_;
};
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32098001

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档