2016-10-02 3 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://ja.cppreference.com/w/cpp/memory/shared_ptr)のように聞こえます。 – Steve

+0

あなたが達成しようとしていることは完全には分かっていませんが、「スマートポインタ」を調べることもできます。 – MrEricSir

答えて

1

これまで提供してきた要件の組み合わせを満たす唯一の方法は、クラス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(); 
     ... 
    } 

    ... 
}; 

を次のようにFoo *ポインタを介してアクセス可能なプロキシを作成および削除することができますその後その

かなり「醜い」実装が見えるかもしれません。そのようなプロキシをあらゆる種類のスマートポインタにラップするかどうかはあなた次第です。これはポイントの横にあります。

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の2つがあります。それらの背後にある一般的な目的は、簡単なリソース管理を提供することですが、あなたが要求するものを満足させます。

+0

私はunique_ptrが生のポインタ(私が欲しいものです)へのアクセスを許可していないので、それは私が探しているものではありませんが、渡すことができるrawを提供する能力を持っていません)。 shared_ptrは未加工のポインタを提供しますが、未処理のポインタに対してdeleteを呼び出した場合、それは基礎となるメモリを削除します – Alex

+0

@Alex:あなたは未加工のポインタを非表示にしたいと言って始めました。今では、生のポインタにアクセスしてそれを渡したいと言っています。それはちょっと自己矛盾している。生ポインタへの直接アクセスを提供すると、それはもはや非表示になりません。まず、あなたが望むものが何であるかを決める必要があります。 – AnT

+0

@AnT私は "実際の"生ポインタを隠したいと思っていますが、 "実際の"ポインタに何の影響も与えずに自由に削除できる "プロキシ"生ポインタを渡したいです。 – Alex

0

はい。それは超簡単。ポインタメンバーをプライベートにしてから、*と - >演算子をオーバーロードしてプライベートメンバーを参照解除します。しかし、それは無意味なことです。極端な場合、「中国語ボックス」プログラミングの極端なケースでは、「抽象化」を作成します。この抽象化は実際には別のデータ型のエイリアスまたはラッパーです。

+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(); 
} 

この方法で、ユーザは、ポインタのアドレスにアクセスすることはできません。それはあなたが望んだことですか?

関連する問題