c++ - 如何将 unique_ptr 用于 pimpl?

标签 c++ c++11 pimpl-idiom unique-ptr

这是我尝试将 unique_ptr 用于 pimpl 时所看到的简化。我选择 unique_ptr 是因为我真的希望类拥有指针 - 我希望 pimpl 指针和类的生命周期相同。

不管怎样,这是标题:

#ifndef HELP
#define HELP 1

#include <memory>

class Help
{

public:

  Help(int ii);
  ~Help() = default;

private:

  class Impl;
  std::unique_ptr<Impl> _M_impl;
};

#endif // HELP

这里是来源:

#include "Help.h"

class Help::Impl
{
public:
  Impl(int ii)
  : _M_i{ii}
  { }

private:

  int _M_i;
};

Help::Help(int ii)
: _M_impl{new Help::Impl{ii}}
{ }

我可以将它们编译成一个库就好了。但是当我尝试在测试程序中使用它时,我得到了

ed@bad-horse:~/ext_distribution$ ../bin/bin/g++ -std=c++0x -o test_help test_help.cpp Help.cpp
In file included from /home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
                 from Help.h:4,
                 from test_help.cpp:3:
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Help::Impl]':
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:245:4:   required from 'void std::unique_ptr<_Tp, _Dp>::reset(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = Help::Impl; _Dp = std::default_delete<Help::Impl>; std::unique_ptr<_Tp, _Dp>::pointer = Help::Impl*]'
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:169:32:   required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Help::Impl; _Dp = std::default_delete<Help::Impl>]'
Help.h:6:7:   required from here
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:63:14: error: invalid application of 'sizeof' to incomplete type 'Help::Impl'

这是众所周知的safety feature .我已经尝试过。

我的问题是,如果我将 Help::Impl 声明放在标题中,它似乎会消除 pimpl 的任何优势。类布局对用户可见。定义是隐藏的,但我可以使用 Help 类和私有(private)成员来做到这一点。此外,包括 Impl 的声明带来了新的 header ,我希望将它们分开。

我错过了什么?人们在 Impl 声明中添加了什么以及在哪里?我做错了 Help dtor 吗?啊!

最佳答案

我相信您的 test_help.cpp 实际上看到了您声明默认的 ~Help() 析构函数。在该析构函数中,编译器也尝试生成 unique_ptr 析构函数,但它需要 Impl 声明。

所以如果你把析构函数定义移到Help.cpp,这个问题应该就没有了。

-- 编辑-- 您也可以在 cpp 文件中定义析构函数为默认值:

Help::~Help() = default;

关于c++ - 如何将 unique_ptr 用于 pimpl?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9020372/

相关文章:

c++ - 构造函数不更新类成员变量

c++ - 将 freeglut 回调包装在一个类中的最优雅的方式

c++ - dll 中的 std::unique_ptr pimpl 使用 Visual Studio 生成 C4251

c++ - 如何判断用户输入命令

c++ - Qwt 绘图自动缩放不工作

c++ - 加入 2 const char*s c++

c++ - 使用公共(public)数据初始化多个 C++ 数组

c++ - 对于从 C++ 中的文件加载的长字符串,正则表达式不匹配任何内容

c++ - C++ 不能消除 pimpl 成语吗?

c++ - 使用 pimpl 的类移动不会编译