2010-12-14 11 views
0

私は次の設定があるコードで作業しています。私はそれを隠すかのクライアントのためにそれを無効にしたいと思いますので、保護された外部リソースの使用

struct data 
{ 
     void change_safe_member(){} 
     void read_data(){} 
     void change_unsafe_member(){} 
}; 

struct data_processor 
{ 
    std::shared_ptr<data> get_data(){} 
    void return_data(std::shared_ptr<data> my_data) 
    { 
      my_data->change_unsafe_member(); // ONLY data_processor should call this function. 
    } 
}; 

struct client 
{ 
    void foo(std::shared_ptr<data_processor>& my_processor) 
    { 
      auto my_data = my_processor->get_data(); 
      my_data->change_safe_member(); 
      //my_data->change_unsafe_member(); SHOULD NOT BE POSSIBLE TO CALL 
      my_processor->return_data(my_data); 
    } 
}; 

change_unsafe_memberは、プロセッサだけで内部的に使用する必要があります。しかし、私は

struct internal_data 
{ 
     void change_unsafe_member(){} 
}; 

struct data : public internal_data 
{ 
     void change_safe_member(){} 
     void read_data(){} 
}; 

struct data_processor 
{ 
    std::shared_ptr<data> get_data(){} 
    void return_data(std::shared_ptr<data> my_data) 
    { 
      auto internal_data = std::static_pointer_cast<internal_data>(my_data); 
      internal_data->change_unsafe_member(); 
    } 
}; 

誰もがこのような状況で使用するために良好なパターンを知っている...醜いキャストに頼ることなくこれを行うのいずれかの素敵な方法を知らないのか?たぶん訪問者のパターンまたは何か似ている?

EDITは:1友達クラスを宣言することができ、コメントで指摘

として、しかしそこにある一つの問題...以下は動作しません。

struct data 
{ 
     void change_safe_member(){} 
     void read_data(){} 
private: 
     friend class data_processor; 
     virtual void change_unsafe_member(){} 
}; 

struct data_decorator : public data 
{ 
     data_decorator(const std::shared_ptr<data>& decoratee) : decoratee_(decoratee){} 
     void change_safe_member(){decoratee_->change_safe_member();} 
     void read_data(){decoratee_->read_data();} 
private: 
     virtual void change_unsafe_member() 
     { 
      std::cout << "Hello!"; // Add functionality 
      decoratee_->change_unsafe_member(); // Won't work... compiler error 
     } 
     std::shared_ptr<data> decoratee_; 
}; 

// Another example 
struct data_group_decorator : public data 
{ 
     data_group_decorator (const std::vector<std::shared_ptr<data>>& decoratees) : decoratees_(decoratees){} 
     void change_safe_member(){decoratee_->change_safe_member();} 
     void read_data(){decoratee_->read_data();} 
private: 
     virtual void change_unsafe_member() 
     { 
      for(size_t n = 0; n < decoratees_.size(); ++n) 
        decoratees_[n]->change_unsafe_member(); // Won't work... compiler error 
     } 
     std::vector<std::shared_ptr<data>> decoratees_;; 
}; 
+1

からYが前方として効果的に定義する任意の機能のためにXの友情を得ることができますか –

+0

これは実際にこの単純化されたケースではうまくいくはずですが、私はちょっと複雑な例で質問を更新します。 – ronag

+1

また、 'friendly_data_processor :: return_data(.....)'を指定することで、すべての愛があまりにも大きい場合にのみ 'friendly_ness 'を' data_processor'の特定のメンバーに制限することができます。 –

答えて

1

これは継承で行うことができます。

struct Y; 
struct X { 
    friend struct Y; 
private: 
    change_unsafe_member() {} 
}; 
struct Y { 
protected: 
    change_unsafe_member(X& x) { x.change_unsafe_member(); } 
}; 
struct some_other : Y { 
    X x; 
    change_safe_member() { change_unsafe_member(x); } 
}; 

Yから継承するクラスは、それをプライベートにして `data_processor`友人のクラスを宣言?X.

1

あなたの最後の例は、あなたが本当に求めているように見えます。つまり、の派生クラスの階層を持ち、privateメンバー関数をdataに呼び出すことができます。これは、他の場所(「一般的になし」で)答えています:

Why does C++ not allow inherited friendship?

多型が唯一の非仮想メンバーがprotected change_unsafe_member()であることと、あなたの特定のシナリオにいくつかの救済を提供class data_decorator「ほぼ純粋な」仮想基底クラスを作るかもしれません、それをfriendclass dataとする。すべてのデコレータはdata_decoratorから継承し、保護された非仮想メンバーを呼び出します。

関連する問題