2012-09-07 2 views
4

C++ 프라이머 15.8에서 저자가 '클래스 및 상속 처리'에 대해 이야기 할 때 그는 다음과 같이 말했습니다.C++의 핸들 클래스?

'C++의 일반적인 기술은 커버 또는 핸들 클래스를 정의하는 것입니다. 핸들 클래스는 기본 클래스에 대한 포인터를 저장하고 관리합니다. 포인터가 가리키는 객체의 유형은 다양합니다. 기본 또는 파생 형 객체를 가리킬 수 있습니다. 사용자는 핸들을 통해 상속 계층의 작업에 액세스합니다. 핸들은 포인터를 사용하여 해당 작업을 실행하기 때문에 가상 멤버의 동작은 핸들이 실제로 바인딩되는 개체의 종류에 따라 런타임에 달라집니다. 따라서 핸들 사용자는 동적 동작을 얻지 만 포인터 자체를 관리하는 것에 대해 걱정할 필요가 없습니다.

위의 내용은 나에게 스마트 포인터처럼 들립니다. 그러나이 '핸들'의 사용법은 조금 다릅니다. 우리는 그들이 핸들을 첨부 할 수있는 자신의 개체를 만들 수있는 우리의 핸들의 사용자에 싶습니다 '

Handle h(Derived()); // noticed a derived object, not a pointer is used to initialize the handle! 
h->func(); 

그리고 손잡이 (아래 그림 참조)의 후자의 구현은 어떤 핸들에 저자의 의견 증명한다. 핸들은 적절한 유형의 새 개체를 할당하고 새로 할당 된 개체에 사용자 개체를 복사합니다. 그렇게하면 핸들 클래스는 이 객체을 소유하게되며 객체에 첨부 된 마지막 핸들이 사라질 때까지 객체가 삭제되지 않음을 보장 할 수 있습니다. '

public: 
    Base(){} 
    virtual int func(std::size_t n) const {} 
    virtual Base* clone() const { return new Base(*this); } 
}; 

class Derived : public Base { 
public: 
    Derived():Base(){} 
    int func(std::size_t) const; // redefine 
    Derived* clone() const { return new Derived(*this); } 
}; 

class Handle { 
public: 
    Handle(const Base &b):p(b.clone()), use(new std::size_t(1)) { } 
private: 
    Base *p; 
    std::size_t *use; // pointer to shared use count 
}; 

내 질문은 : 이것은 정말로 C++ 또는 OO에서 핸들의 일반적인 의미입니까? 핸들은 내부적으로 사용 횟수를 유지하는 기본 유형의 스마트 포인터 일 수도 있고, 일반적으로 시스템이 가리키는 점과 처리 할 점을 알고있는보다 일반적인 마법 유형 일 수도 있습니다. 왜이 핸들을 사용하면 사용자 개체의 사본을 만들어 그 사본을 기반으로 use-count를 수행해야합니까?

누구든지 도움이 되나요?

감사 ++ 현대 C에서

답변

4

관용적 상응하는 것 : 일반적으로

std::shared_ptr<Base> h{std::make_shared<Derived>()}; 

하는 "핸들"타입의 삭제의 형태를 의미한다, 핸들을 처리하는 코드가되지 않도록 기능이 어떻게 구현되는지에 대한 세부 사항을 알아야합니다.

표시된 코드가 clone을 사용하여 개체를 복사하는 이유는 정확하게 형식 지우기를 수행하기위한 것입니다. 그 시점에서 clone 메서드가 호출되면 Derived 개체의 실제 유형에 대한 정보가 지워집니다. 구현 품질면에서 코드는 스레드로부터 안전하지 않으며 레거시 C++와는 관련이 없지만 스레드 인식 메모리 모델을 사용하는 최신 C++의 경우에는 문제가됩니다. 명백히 예외 안전하지도 않습니다. shared_ptr과 같은 표준 라이브러리 클래스에 예외 안전을 위임하는 것이 훨씬 낫습니다. 마지막으로 Base 클래스에는 가상 소멸자가 없습니다.

+0

감사합니다. 내 질문은 왜 (Base * p에 저장된) 객체의 COPY가 필요한지와 더 관련이있다. 왜 스마트 포인터가 할 것처럼 핸들이 'new'에서 반환 된 기본 포인터를 받아들이도록 할 수없고 use-count만을 추적 할 수는 없습니다. '복제'는 형식에 구애받지 않는 가상 생성자와 같은 것으로 이해합니다. – user1559625

+0

@ user1559625'clone'에는 약간의 오버 헤드가 있지만 raw 할당 포인터를 전달하는 것보다 안전합니다. 'shared_ptr'는'make_shared'를 사용하여 원시 할당 된 포인터를 피하지만, C++ 11 이후에만 가능합니다 (rvalue 참조 완벽한 전달 및 가변 템플릿을 사용합니다). – ecatmur

관련 문제