私はPIMPLイディオムを使用しています。具体的には、this postから提供されたテンプレートを使用しています。下のクラスのセットを考えるとVS2015アップデート3は、私はエラーがコンパイル取得していてコンパイルする:(ソースファイルSRC \ A.cppをコンパイル)未定義の型「C :: C_impl」のPIMPLイディオムを使用すると、このタイプが不完全なのはなぜですか?
エラーC2027の使用を
エラーC2338は不完全な型(ソースファイルsrc \ A.cppのコンパイル)を削除できません。
警告C4150不完全な型 'C :: C_impl'へのポインタの削除。 (コンパイルソースファイルSRC \ A.cpp)と呼ばれるデストラクタない
何私は何かが自動的に生成されることから~C()
を妨げているが、私は何を理解していないと信じて私をリードされ、C::~C()
のコメントを外すことによって、これを解決することができます。
- Tを破壊することができない非静的データメンバーを有する(デストラクタを削除またはアクセスできないた)
:削除されたように、次のいずれかが真である場合 this referenceによれば、タイプTのデストラクタが暗黙的に定義されています- Tには、破壊できない直接的または仮想的な基底クラスがあります(削除された、またはアクセスできないデストラクタを持っています)。
- Tは共用体であり、トリガーではないデストラクタを持つ変形メンバを持っています。
- 暗黙的に宣言さデストラクタは仮想(基底クラスが仮想デストラクタを持っているので)と、あいまいな、削除、またはアクセス不可能な関数の呼び出しで解放関数(delete演算子()の結果のルックアップです。
アイテム#2、3、および4は明らかにC
には適用されません、と私はpimpl<>
(C
年代唯一のメンバー)は、明示的にデストラクタを定義するため、#1が適用されることを信じていません。
誰かが説明していただけます何が起こっているのですか?
A.h
#pragma once
#include <Pimpl.h>
class A
{
private:
struct A_impl;
pimpl<A_impl> m_pimpl;
};
B.h
#pragma once
#include "C.h"
class B
{
private:
C m_C;
};
C.h
#pragma once
#include <Pimpl.h>
class C
{
public:
// Needed for the PIMPL pattern
//~C();
private:
struct C_impl;
pimpl<C_impl> m_pimpl;
};
A.cpp
#include <memory>
#include "A.h"
#include "B.h"
#include <PimplImpl.h>
struct A::A_impl
{
std::unique_ptr<B> m_pB;
};
// Ensure all the code for the template is compiled
template class pimpl<A::A_impl>;
C.cpp
#include <C.h>
#include <PimplImpl.h>
struct C::C_impl { };
// Needed for the PIMPL pattern
//C::~C() = default;
// Ensure all the code for the template is compiled
template class pimpl<C::C_impl>;
は完全を期すために、後からPIMPL実装は上記で参照:
pimpl.h
#pragma once
#include <memory>
template<typename T>
class pimpl
{
private:
std::unique_ptr<T> m;
public:
pimpl();
template<typename ...Args> pimpl(Args&& ...);
~pimpl();
T* operator->();
T& operator*();
};
PimplImpl。時間
#pragma once
#include <utility>
template<typename T>
pimpl<T>::pimpl() : m{ new T{} } {}
template<typename T>
template<typename ...Args>
pimpl<T>::pimpl(Args&& ...args)
: m{ new T{ std::forward<Args>(args)... } }
{
}
template<typename T>
pimpl<T>::~pimpl() {}
template<typename T>
T* pimpl<T>::operator->() { return m.get(); }
template<typename T>
T& pimpl<T>::operator*() { return *m.get(); }
上記のコードについての注意事項:私は私のライブラリの消費者にA
とC
を公開し、内部B
を維持しようとしている
- 。
- ここにB.cppはありません。それはempyです。
それは意味があります、私はそれが使用の時点で生成されたことを認識していませんでした。ありがとう! –