これは、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の利点がなくなるように見えることです。クラスレイアウトはユーザーに表示されます。定義は非表示ですが、ヘルプクラスとプライベートメンバーを使用して行うこともできます。また、Implの宣言を含めると、別にしたい新しいヘッダーが追加されます。
私は何が欠けていますか?人々はImpl宣言に何を入れますか?ヘルプを間違っていますか?ああ!
Test_help.cppには、デフォルトとして宣言した~Help()
デストラクタが実際に表示されると思います。そのデストラクタでは、コンパイラはunique_ptr
デストラクタも生成しようとしますが、そのためにはImpl
宣言が必要です。
したがって、デストラクタ定義をHelp.cppに移動すると、この問題は解消されます。
-編集-define cppファイルのデストラクタもデフォルトにできます:
Help::~Help() = default;
nique_ptr 定義からこれに注意してください:
std :: unique_ptrは、pImplイディオムのハンドルとしての使用を容易にするためなど、不完全な型Tに対して構築できます。デフォルトの削除機能を使用する場合、Tは、削除機能が呼び出されるコードのポイントで完了する必要があります。これは、デストラクタ、割り当て演算子の移動、std :: unique_ptrのメンバー関数のリセットで発生します。