2017-03-25 14 views
1

class A : public BB에서 상속 받았다고 가정 해 보겠습니다. 나는 A의 메소드를 노출하고자하는데, 이는 B의 메소드를 호출합니다.Pimpl 관용구에서의 C++ 계승

는 지금은 pimpl 관용구에서 이러한 방법을 노출 할 - 난 정말이 작업을 수행하는 방법을 잘 모르겠어요 :

  • 모두 AB 별도의 구현 클래스 B::impl을받을 수 있나요 및 A::impl : public B::impl 등의 구현이 서로에게서 물려 받습니까? 일반 클래스는 다음 상속하지 않습니다 : class Aclass B?

    구현이 private이기 때문에 가능하지 않습니다.

  • 구현은 B::implA::impl를 서브 클래 싱하지 않지만 노출 된 클래스는 class Bclass A : public B을한다. 그렇다면 A::impl의 메소드는 부모의 메소드를 B::impl에 호출 할 수 있습니까?

  • 인수의 포인터를 통해 - 아래 예제를 참조하십시오.

감사

편집 : 여기있는 예제 코드 -이 맞습니까?

test.hpp

#include <iostream> 

class B { 
private: 
    class impl; 
    std::unique_ptr<impl> pimpl; 

public: 
    B(); 
    ~B(); 
    B(B&&) = default; 
    B(const B&) = delete; 
    B& operator=(B&&); 
    B& operator=(const B&) = delete; 

    void my_func() const; 
}; 

class A : public B { 
private: 
    class impl; 
    std::unique_ptr<impl> pimpl; 

public: 

    A(); 
    ~A(); 
    A(A&&) = default; 
    A(const A&) = delete; 
    A& operator=(A&&); 
    A& operator=(const A&) = delete; 

    void access_my_func(); 
}; 

Test.cpp에 당신이 다음 B에서 서브 클래스 경우

#include "test.hpp" 

// Implementation of B 
class B::impl 
{ 
public: 
    impl() {}; 

    void impl_my_func() { 
     std::cout << "impl_my_func" << std::endl; 
     return; 
    }; 
}; 

// Constructor/Destructor of B 
B::B() : pimpl{std::make_unique<impl>()} {}; 
B::~B() = default; 
B& B::operator=(B&&) = default; 

// Exposed method of B 
void B::my_func() const { 
    std::cout << "B::my_func" << std::endl; 
    pimpl->impl_my_func(); 
    return; 
}; 


// Implementation of A 
class A::impl 
{ 
public: 
    impl() {}; 

    void impl_access_my_func(const A& a_in) { 
     std::cout << "impl_access_my_func" << std::endl; 
     a_in.my_func(); 
     return; 
    }; 
}; 

// Constructor/Destructor of A 
A::A() : pimpl{std::make_unique<impl>()} {}; 
A::~A() = default; 
A& A::operator=(A&&) = default; 

// Exposed method of A 
void A::access_my_func() { 
    std::cout << "A::access_my_func" << std::endl; 
    pimpl->impl_access_my_func(*this); 
    return; 
}; 




// Later in the main.cpp file 
int main() { 

    // Make an object 
    A my_A_object; 
    my_A_object.access_my_func(); 

    return 0; 
}; 
+1

[고려] (http://stackoverflow.com/q/825018/7571258) pimpl이 실제로 사용 사례에 적합한 관용구라면.순수 가상 기본 클래스는 구문 상 오버 헤드가 적은 대안이 될 수 있습니다. 특히 상속이 관련 될 때 그렇습니다. – zett42

+0

고마워요! 나는 이것에 대해 생각하지 않았다. 이 프로젝트의 최종 목표는 API이므로, pimpl은 구현 세부 정보를 숨기고 향후 변경 후 이전 버전과의 호환성을 보장하는 인기있는 방법입니다. 순수한 가상 기본 클래스를 동일한 목적으로 사용할 수 있는지 확실하지 않습니다. – Kurt

+0

다음과 같이 사용할 수 있습니다. [이 질문에 대한 예제] (http://stackoverflow.com/q/3092444/7571258)를 참조하십시오. ABI 호환성에 문제가있을 수 있습니다. [이 답변] (http://stackoverflow.com/a/2330745/7571258)에 대한 의견을 참조하십시오. – zett42

답변

1

하면, A는 그것은해야 클래스 B의 인터페이스를 호출 할 수 있어야한다 구현에 의존 할 필요가 없습니다.

Pimpl-Ideom은 C++의 제한 사항을 처리하기위한 방법 일 뿐이므로 클래스의 개인, 보호 및 공용 부분 선언을 분리 할 수 ​​없습니다. 클래스의 비공개 부분을 클래스 사용자에게 공개하고 하위 클래스를 원하지 않는 사용자에게 보호 된 부분을 노출하고 싶지 않으므로 Pimpl-Ideom은 이러한 부분을 헤더 파일에서 멀리 이동시킵니다.

귀하의 질문에 대답하기 :

  • 클래스 A가 B를 서브 클래스해야합니다, 그 OOP에 대해 무엇이다.
  • 클래스 A :: impl은 B :: impl을 사용하여 작업을 완료하지 않아도됩니다.
  • 극단으로 가고 싶다면 A :: impl이 서브 클래 싱 할 수있는 B :: protected_impl을 상상할 수 있습니다. 이 작업을하려면 A :: impl이 사용할 수 있도록 protected_impl 선언으로 별도의 헤더를 만들어야합니다.
+0

감사합니다. 이 점들은 모두 의미가 있습니다. 그렇다면'class A :: impl'은 어떻게 할 수 있습니까? 부모로부터 메소드를 호출 할 필요가 있다면 객체에 대한 포인터를 전달하는 유일한 방법이다 (예제'void impl_access_my_func (const A & a_in)')? – Kurt