2016-06-20 3 views
0

나는 C++에서 pimpl를 사용하는 방법을 찾고 있었다, 나는 튜토리얼에이 코드 조각을 발견왜 우리는 pimpl에서 'new'를 사용합니까?

// In MyClass.h 

class MyClassImp;     // forward declaration of Pimpl 

class MyClass 
{ 
public: 
    MyClass(); 
    ~MyClass(); 

    MyClass(const MyClass &rhs); // undefined for simplicity 
    MyClass& operator=(MyClass); 

    void Public_Method(); 

private: 
    MyClassImp *pimpl_;    // the Pimpl 
}; 

// In MyClass.cpp 

#include "MyClass.h" 

class MyClassImp 
{ 
public: 
    void Private_Method() {} // dummy private function 

    int private_var_;   // a private variable 
}; 

MyClass::MyClass() : pimpl_(new MyClassImp()) 
{ 
} 

MyClass::~MyClass() 
{ 
    delete pimpl_; 
} 

void MyClass::Public_Method() 
{ 
    pimpl_->Private_Method();  // do some private work 

    pimpl_->private_var_ = 3; 
} 

하지만 힙에 MyClassImp을 할당하는 이유 주위에 내 머리를 가져올 수 없습니다 스택에 변수를 사용할 수 없습니까? 우리는 분리 .H 및 .CPP 파일에 MyClassImp을 넣어에서 MyClass.h의 .H 포함 된 경우

및 MyClassImp의 pimpl_을 사용합니다 :

는 명확히하기 위해 (포인터없이) 동일한 결과를 얻지 못했습니까? MyClassImp의 구현이 변경되면 호출자 (MyClass)는 변경 및 재 조합 할 필요가 없습니다. (그들은 여전히 ​​다시 링크해야합니다)

+2

* 어느 스택? MyClass :: MyClass 중 하나입니까? 일단 생성자가 끝나면 파멸됩니다. 전화 한 사람? * 당신은 호출자를 모릅니다. * – DevSolar

+1

당신은 왜 당신이'MyClassImp * pimpl_; '대신'MyClassImp pimpl_; '? – NathanOliver

+1

"스택에서"주소를 지정하려면 - 함수 호출에서 원하는 스택 프레임 내에 있습니까? 또한 자동 저장 기간을 사용하지 않는 이유를 설명하기 위해 연습의 요점은 'MyClassImp'의 정의를 숨기는 것입니다. 직접적인 구성원이라면 그 크기 (따라서 정의)를 알아야 할 것입니다. – Angew

답변

1

포인터로 인해 새로해야합니다. Impl의 정의를 선언 (예 : 포함하지 않음) 할 수 있도록 포인터가 존재합니다. Impl의 정의를 헤더에 포함 시키면 그것을 포함하는 모든 파일에 노출됩니다.

5

pimpl-idiom의 트릭은 헤더 파일에서 포인터 만 사용된다는 것입니다. 즉, 실제로 선언문을 제공하지 않고도 클래스의 전달 선언을 사용할 수 있습니다.

나중에 헤더를 사용하여 헤더 나 다른 컴파일 단위에 영향을주지 않고 (cpp에서) 선언을 변경할 수 있습니다.

이것은 특히 라이브러리를 처리 할 때 유용합니다.

+0

우리는 단순히 MyClassImp pimpl_을 사용하고 분리 된 파일에 MyClassImp를 넣고 MyClassImp.h를 MyClass.h에 포함 시키십시오. MyClassImp, MyClass.h에 대한 변경 사항은 바로 재 해석 할 필요가 없습니까? – user1701840

+0

MyClassImp의 구현 만 변경하면 가능하지만 인터페이스 (= 헤더)도 변경하면 다시 컴파일해야합니다. 포인터를 사용하면 MyClassImp.h를 포함하지 않기 때문에 원하는 것을 무엇이든 할 수 있습니다. – Anedar

1

기본 문제는 스택에 impl을 넣으려면 코드가 호출 사이트에서 impl 클래스의 크기를 알아야하기 때문에 impl의 클래스 정의가 노출되어야한다는 것입니다. impl의 전체 요점은 클래스 정의를 숨기는 것입니다.

관련 문제