Question

J'ai une classe qui contient, entre autres, une std :: liste. Je veux exposer cette liste, mais seulement dans une telle manière que la structure et les données qu'il contient sont en lecture seule, mais peuvent encore être utilisés avec itérateurs.

La I façon l'ai « travail » est atm à renvoyer une copie de la liste. Ce congé de ma classe « sûr » mais bien sûr, ne fait rien pour arrêter l'appelant de modifier leur copie de la liste et ne pas obtenir les bonnes données.

Y at-il une meilleure façon?

Était-ce utile?

La solution

Pourquoi ne pas retourner un const std::list& à la place?

Autres conseils

Au lieu d'exposer la liste elle-même (tout) juste exposer const_iterators à son début et à la fin. Voir cbegin() et cend() pour l'aider à le faire ...

Retour une référence const:

const std::list<T>& getList() const;

ou tout simplement revenir const itérateurs:

std::list<T>::const_iterator getListBegin() const;
std::list<T>::const_iterator getListEnd() const;

Il y a un problème de dépendance à exposer un Membre de données au monde extérieur.

Si vous décidez de changer votre attribut pour quelque chose de mieux (car list sont le dernier conteneur de station), ou parce que vous avez une nouvelle exigences, tous vos clients seront touchés, et ce qui est mauvais.

Une alternative simple est d'offrir un typedef:

typedef std::list<Foo>::const_iterator const_iterator;

Si vos clients utilisent votre alias, il est une simple question de recompiler le code.

Une autre alternative est de créer votre propre classe iterator (pas difficile), qui intégrera la iterator réelle.

class const_iterator
{
public:

private:
  typedef std::list<Foo>::const_iterator base_type;
  base_type mBase;
};

Il vous suffit de l'avant toutes les opérations à l'itérateur réelle, et vos clients (bien qu'ils auront à recompiler si vous changez votre conteneur) ne peut pas utiliser accidentellement un type non replié.

Ensuite, la 3ème solution est similaire à la première, sauf que vous abstrait du type ... il est tout à fait inefficace si (pour une liste), donc je conseillerais pas vraiment: itérateurs sont censés être pas cher pour copier, vous ne voulez pas quoi que ce soit new.

class foo {
  private:
     typedef std::list<bar> bar_cont_t;

  public:
     typedef bar_const_t::const_iterator bar_const_iterator;

     bar_const_iterator bar_begin() const {return bar_data_.begin();}
     bar_const_iterator bar_end  () const {return bar_data_.end  ();}

     // whatever else

  private:
     bar_cont_t bar_data_;
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top