62

これは、pimpl に unique_ptr を使用しようとしたときに表示されるものを簡略化したものです。クラスにポインターを所有させたいので、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'

これはよく知られている安全機能です。フォローしてみました。

私の問題は、Help::Impl 宣言をヘッダーに入れると、pimpl の利点がなくなるように見えることです。クラスのレイアウトはユーザーに表示されます。定義は非表示になっていますが、Help クラスとプライベート メンバーを使用してそれを行うこともできました。また、Impl の宣言を含めることで、別個に保持したかった新しいヘッダーが取り込まれます。

私は何が欠けていますか?人々は Impl 宣言に何をどこに入れますか? Help dtor のやり方が間違っていますか? ああ!

4

2 に答える 2

86

あなたの test_help.cpp は、~Help()デフォルトと宣言したデストラクタを実際に見ていると思います。そのデストラクタでは、コンパイラもデストラクタを生成しようとしますが、そのための宣言unique_ptrが必要です。Impl

したがって、デストラクタの定義を Help.cpp に移動すれば、この問題は解決するはずです。

-- 編集 -- cpp ファイルでデストラクタをデフォルトに定義することもできます。

Help::~Help() = default;
于 2012-01-26T15:24:13.830 に答える