Pimpl

최근의 C++ 컴파일러(GCC, Clang, MSVC 등)은 빠른 컴파일 속도와 컴파일 동작이 점점
더 단계적/점진적으로 변화고 있다.
(컴파일시, 번역 단위(translation unit) 전체를 새로 생성하는 것이 아닌, 변경된 정의 부분만 새로 만들고
나머지는 재활용함
Pimpl(Pointer to Implementation)
구현부를 포인터로 참조하는 관례를 말한다.
struct Person{
std::string name;
void greet();
Person(); // PersonImpl /
~Person();
class PersonImpl;
PersonImpl* impl;
};
struct Person::PersonImpl{ // Person PersonImpl
void greet(Person* p); // PersonImple .cpp
}
Person::Person(): impl(new PersonImpl) {}
Person::~Person(){ delete PersonImpl; }
void Person::greet(){
impl->greet(this);
}
void Person::PersonImpl::greet(Person* p){
printf("hello %s", p->name.c_str());)
}
Pimpl 사용 장점
- 클래스 구현부를 숨김
Person 클래스가 많은 수의 private/protected 멤버를 가지더라도, 헤더를 통해 모두 클라이언트에게 노출된다.
Pimpl 관례를 사용하면, 꼭 필요한 public 인터페이스만 노출해도 된다.

- 바이너리 호환성 보증하기 쉬움
숨겨진 구현 클래스에 대한 수정은 바이너리 호환성에 영향을 미치지 않는다.

- 사용자에게 헤더 인클루드를 최소화 할 수 있다.
Person이 private 멤버로 vector<string>을 가질 경우,
Person.h는 #include <string>, #include <vector>를 해주어야 한다.
(Person.h를 사용하는 사용자도 강제로 <vector>, <string>을 인클루드 시킴)
Pimpl 관례 사용 시, Person.cpp에서만 인클루드 해주면 된다.
이와 같이 Pimpl 관례를 사용하면, 깨끗하고 안정적인 헤더를 유지할 수 있다.
(컴파일 소요 시간도 줄여 준다.)

Pimpl은 브릿지 패턴의 하나의 얘다.
Pimpl의 Impl타입 포인터는 공개용 인터페이스와 숨겨야 할 .cpp 파일의 세부 구현을 연결하는 브릿지 역할