受保护的外部资源使用

时间:2010-12-14 11:09:59

标签: c++ design-patterns c++11

我正在使用一些代码,我有以下设置。

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

任何人都知道在这种情况下使用的好模式?也许访客模式或类似的东西?

编辑:

正如评论中所指出的那样,可以申报朋友类,但是有一个问题......以下内容不起作用。

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_;;
};

2 个答案:

答案 0 :(得分:1)

你的最后一个例子看起来像你真正要求的是继承的友谊;即,您希望拥有decorator层次结构 - 派生类,这些类都可以在private中调用data成员函数。在其他地方得到了回答(通常没有“):

Why does C++ not allow inherited friendship?

多态性可能会在您的特定场景中提供一些缓解,使class data_decorator成为“几乎纯粹的”虚拟基类,唯一的非虚拟成员为protected change_unsafe_member(),并将其作为{{1} } friend。所有装饰器都将从class data继承,并调用其受保护的非虚拟成员。

答案 1 :(得分: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继承的类都可以为Y定义为X的任何函数获得X的友谊。