2016-10-02 2 views
0

원시 포인터의 기능에 대한 액세스를 제공하는 "프록시"또는 "가짜"포인터 뒤에 원시 포인터를 숨기는 방법이 있습니까?"프록시"포인터를 제공하여 원시 포인터를 숨기기

과 같이 볼 수있는 원시 포인터에 대한 관리 클래스는 다음과 같습니다

template<typename T> 
class hidden_ptr 
{ 
public: 
    hidden_ptr(T *RawPointer); 
    ~hidden_ptr(); 

    T *get() 
    { 
     return new proxy_pointer<T>(raw_pointer) 
    } 
}; 

그런 다음이 기능을 사용하려면 방법이 있으면

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

    void do_bar(); 
    void do_bar2(); 
}; 

int main() 
{ 
    Foo *raw_pointer = new Foo(); 
    hidden_ptr<Foo> hidden(raw_pointer); 

    Foo *proxy = hidden.get(); 

    proxy->do_bar(); 
    proxy->do_bar2(); 

    delete proxy; //The raw pointer is still safe till the hidden object destructs 
} 

, 무엇 proxy_ptr의 모습?

+0

질문에 대답하려면 : 예, 대부분의 경우이를 수행 할 수있는 방법이 있습니다. –

+0

[shared_ptr] (http://en.cppreference.com/w/cpp/memory/shared_ptr)과 유사합니다. – Steve

+0

달성하려는 목표에 대해 확실하지 않지만 "스마트 포인터"를 조사 할 수 있습니다. – MrEricSir

답변

1

지금까지 제공 한 요구 사항의 조합을 충족시키는 유일한 방법은 클래스 Foo을 종류의 이중 모드 클래스로 만드는 것입니다. 즉, 기본 (숨겨진) 객체 및 공개로 작동 할 수 있어야합니다. 프록시, 즉 다른 Foo 객체로 프록시합니다. 당신이 작성하고 Foo * 포인터를 통해 액세스 프록시를 삭제할 수 있습니다 그 후

class Foo 
{ 
    Foo *redirect_to = nullptr; 
    Foo(Foo *redirect_to) : redirect_to(redirect_to) { ... } 

public: 
    Foo() { ... } 
    ~Foo() { ... } 

    Foo *get_proxy() { return new(this); } 

    void do_bar() { 
     if (redirect_to) { 
     return redirect_to->do_bar(); 
     ... 
    } 

    void do_bar2() { 
     if (redirect_to) { 
     return redirect_to->do_bar2(); 
     ... 
    } 

    ... 
}; 

을 다음과 같이 그

매우 "추악한"구현을 보일 수 있습니다. 그러한 프록시를 어떤 종류의 스마트 포인터로 랩핑할지 여부는 당신에게 달려 있습니다. 이것은 요점입니다. 원하는 경우

int main() 
{ 
    Foo *raw_pointer = new Foo(); 

    Foo *proxy = raw_pointer->get_proxy(); 

    proxy->do_bar(); 
    proxy->do_bar2(); 

    delete proxy; 
} 

다시 말하지만, 당신은 믹스로 hidden_ptr를 추가 할 수 있습니다.

위의 내용을 자세히 살펴보면 모두 개체가 숨겨진 구현 클래스를 가리키는 pImpl 스타일 구현을 통해 훨씬 더 우아하게 구현 될 수 있음을 알 수 있습니다. 그러나 당신은 (내가 지금까지 알아낼 수 없었던) 어떤 이유로 그 접근법을 좋아하지 않는 것처럼 보입니다.

+0

나는 당신이 옳다고 믿습니다. 리디렉션을 템플릿 스타일로 적용하는 좋은 방법이 없다는 것은 유감입니다. – Alex

0

두 가지가 있습니다. std::unique_ptrstd::shared_ptr입니다. 배후의 일반적인 의도는 쉬운 리소스 관리를 제공하는 것이지만, 사용자가 요청한 것을 만족시킵니다.

+0

그들은 꽤 원하는 원시 포인터 (어떤 내가 원하는)에 대한 액세스를 허용하지 않는 unique_ptr 그러나 내가 원하는 전달할 수있는 원시 제공 할 수있는 기능이없는). shared_ptr은 미가공 포인터를 제공하지만 미처리 포인터에 delete를 호출하면 기본 메모리를 삭제합니다. – Alex

+0

@Alex : 미가공 포인터를 숨기고 싶다고 말하기 시작했습니다. 이제 원시 포인터에 액세스하여 전달하려고한다고 말합니다. 그것은 다소 자기 모순입니다. 원시 포인터에 대한 직접 액세스를 제공하면이 포인터는 더 이상 숨겨지지 않습니다. 첫째, 원하는 것이 무엇인지 정확하게 결정해야합니다. – AnT

+0

@AnT "실제"원시 포인터를 숨기고 싶습니다만, "실제"포인터에 아무런 결과없이 지울 수있는 "프록시"원시 포인터를 전달하려고합니다. – Alex

0

예. 그건 매우 쉬워요. 포인터 멤버를 private으로 설정 한 다음 * 및 -> 연산자를 오버로드하여 private 멤버를 참조 해제합니다. 그러나 그것은 또한 무의미한 일입니다. "중국어 상자"프로그래밍의 극단적 인 경우, "추상화"를 작성하는 곳은 사실 별칭이거나 다른 데이터 유형의 래퍼입니다.

+0

제안 된'std :: observer_ptr' (http://en.cppreference.com/w/cpp/experimental/observer_ptr)을 "중국어 상자"프로그래밍의 한 예로 생각하십니까? – AnT

0

은 당신이 뭔가를 할 수 있습니다 :

#include <iostream> 

template<typename T> 
class hidden_ptr 
{ 
public: 
    hidden_ptr() = delete; 
    hidden_ptr(hidden_ptr const&) = delete; 
    hidden_ptr(T data) : ptr_(new T{data}) {} 
    void operator=(hidden_ptr const&) = delete; 
    ~hidden_ptr() {delete ptr_;} 

    T* operator->() {return ptr_;}; 
    void reset(T data) {this->~hidden_ptr(); ptr_ = new T{data};} 
    void set(T value) {*ptr_ = value;} 
    T get() {return *ptr_;} 

private: 
    T* ptr_; 
}; 

class A 
{ 
public: 
    void print() {std::cout << "A::print" << std::endl;}  
}; 

int main() 
{ 
    hidden_ptr<int> ptr_int(5); 
    hidden_ptr<A> ptr_a(A{}); 
    ptr_int.reset(10); 
    std::cout << ptr_int.get() << std::endl; 
    ptr_a->print(); 
} 

이 방법은 사용자가 포인터 주소를 액세스 할 수 없습니다. 그게 니가 원하는거야?

관련 문제