【问题标题】:Protected External Resource Usage受保护的外部资源使用
【发布时间】:2011-05-25 05:20:14
【问题描述】:

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

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

有人知道在这种情况下使用的好模式吗?也许是访问者模式或类似的东西?

编辑:

正如 cmets 中所指出的,可以声明朋友类,但是有一个问题......以下将不起作用。

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

【问题讨论】:

  • 将其设为私有并声明data_processor 为好友类?
  • 这在这个简化的情况下确实可以工作,我稍后会用一个更复杂的例子来更新我的问题。
  • 您还可以指定friend void data_processor::return_data(.....),仅当所有包容的爱都太多时,才将“友好”限制为data_processor 的特定成员。
  • 您的示例令人困惑 - 为什么您都使用嵌入(通过继承)和 pimpl(通过具有显式 decoratee_ 成员)?
  • 试图澄清示例。另请参阅en.wikipedia.org/wiki/Decorator_pattern。

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


【解决方案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 的友谊。

【讨论】:

    【解决方案2】:

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

    Why does C++ not allow inherited friendship?

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

    【讨论】:

      猜你喜欢
      • 2015-09-05
      • 2015-03-19
      • 2011-06-14
      • 2013-10-22
      • 2018-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-23
      相关资源
      最近更新 更多