Я работаю с некоторым кодом, где у меня есть следующая настройка.Использование защищенных внешних ресурсов
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:
Как было отмечено в комментариях один мог объявить другу классов, есть, однако, одна проблема ... следующий не будет работать.
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' другу по электронной почте класс? –
Это действительно работает в этом упрощенном случае, я обновляю свой вопрос с помощью более сложного примера. – ronag
Вы также можете указать 'friend void data_processor :: return_data (.....)', чтобы ограничить «дружественность» определенному члену 'data_processor', только если все охватывающие любовь слишком много. –