Защищенное использование внешних ресурсов - PullRequest
0 голосов
/ 14 декабря 2010

Я работаю с некоторым кодом, где у меня есть следующие настройки:

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 ]

1 голос
/ 14 декабря 2010

Вы можете сделать это с помощью наследования.

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, может получить дружбу X для любых функций, которые Y определяет так же эффективно, как и от X.

1 голос
/ 14 декабря 2010

Ваш последний пример выглядит так, как будто вы действительно просите о наследственной дружбе; т.е. вы хотите иметь иерархию decorator - производных классов, которым всем разрешено вызывать функцию-член private в data. Это ответ (с «вообще нет») в другом месте:

Почему C ++ не допускает наследственную дружбу?

Полиморфизм может обеспечить некоторое облегчение в вашем конкретном сценарии, сделать class data_decorator «почти чистым» виртуальным базовым классом, с единственным не виртуальным членом, являющимся protected change_unsafe_member(), и сделать его, в свою очередь, friend из class data , Все декораторы наследуют от data_decorator и вызывают его защищенный не виртуальный член.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...