Je travaille avec du code où j'ai la configuration suivante.Utilisation de ressources externes protégées
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);
}
};
Le change_unsafe_member ne doit être utilisé en interne par le processeur, donc je voudrais le cacher ou le désactiver pour le client. Mais je ne connais pas de belles façons de le faire sans avoir recours à des moulages laides ...
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();
}
};
Quelqu'un sait d'un bon modèle à utiliser dans des situations comme celle-ci? Peut-être un modèle de visiteur ou quelque chose de similaire?
EDIT:
Comme indiqué dans les commentaires on pourrait déclarer les classes d'ami, il y a cependant un problème ... ce qui suit ne marchera pas.
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_;;
};
le rendre privé et de déclarer 'data_processor' une classe ami? –
Cela fonctionnerait en effet dans ce cas simplifié, je vais mettre à jour ma question avec un exemple plus compliqué dans un instant. – ronag
Vous pouvez également spécifier 'friend void data_processor :: return_data (.....)' pour restreindre "convivialité" à un membre particulier de 'data_processor' que si tout l'amour englobant est trop. –