저는 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()
주석을 해제하여이 문제를 해결할 수 있습니다. 다음 중 하나에 해당하는 경우 this reference에 따르면, 타입 T 소멸자 암시 삭제 같이 정의된다
및 해제 기능을위한 룩업 (기본 클래스 가상 소멸자 때문에)
- T 비 정적 데이터 (삭제되거나 액세스 소멸자) 파괴 할 수없는 부재를 구비
- T는 파괴 할 수없는 직접 또는 가상 기본 클래스가 있습니다 (삭제되거나 액세스 할 수없는 소멸자가 있음)
- T는 공용체가 아니며 변형자가 아닌 소멸자가있는 변형 멤버가 있습니다.
- 암시 적 선언 소멸자 가상이다 (연산자 (삭제) 삭제 모호하거나 액세스 함수에 대한 호출을 초래한다.
항목 # 2, 3, 분명히 4 C
에 적용되지 않습니다, 나는 pimpl<>
(C
's의 유일한 구성원)이 명시 적으로 소멸자를 정의하기 때문에 # 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가됩니다.
의미가 있습니다. 사용 시점에 생성 된 것을 알지 못했습니다. 감사! –