Je vous demande d'excuser le temps de réponse, je n'ai pas de connexion internet permanente pour l'instant.
Ce qu'il faut comprendre, c'est que l'encapsulation n'est pas seulement le fait de mettre tous les membres en accessibilité privée. Cela ne représente que la première étape pour que l'encapsulation soit "utile".
Si, une fois que tu as placé ton std::vector dans l'accessibilité privée, tu te contente de fournir un getVector et un setVector, tu n'encapsule absolument rien, pour la simple et bonne raison que non seulementl'utilisateur de ta classe doit savoir que tu utilises la classe std::vector (et non n'importe quelle autre classe de ton choix, et les possibilités sont très nombreuses), mais aussi (et surtout) parce que la fonction setVector permet à l'utilisateur de remplir un vector "comme bon lui semble" -- sans que ta classe qui l'utilise n'ait la moindre possibilité de s'assurer de la validité des données qui seront placées dans ce vector -- avant de dire à la classe "tiens, utilises plutôt ce vector à la place de celui que tu utilisais avant".
En agissant de la sorte, tu crois avoir encapsulé tes données, mais tu t'es en fait contenté de te faire du mal pour rien, parce que la manière dont les informations sont placée dans le vector échappe totalement au contrôle de la classe qui l'utilise.
En plus, comme il a déjà été dit, si tu décide -- pour une raison ou une autre -- d'utiliser autre chose qu'un std::vector (je verrais bien un std::set, vu que chaque acteur ne devrait en théorie apparaitre qu'une seule fois dans la liste des acteurs ), il n'y aura pas que la classe qui utilise le vector que tu devras modifier, mais potentiellement tout le code qui manipule cette classe.
Au lieu de limiter les modifications du code à quelques fonctions, c'est potentiellement tout ton projet qui devra être mis à jour, tout cela pour une modification sommes toutes "mineure".
Le but de l'encapsulation est réellement de permettre d'avoir un minimum de code à modifier dans le cas où tu déciderais de changer d'idée en ce qui concerne l'existant. Le fait de fournir un accesseur et un mutateur rende impossible de garantire cette particularité.
C'est pour cela que je te disais que tu devrais sans doute commencer par créer un alias de type sur l'itérateur : la plupart des collections (hormis std::stack, std::queue et quelques autres) te permettent déjà de savoir quel est le type d'itérateur -- aussi bien les itérateurs constants que non constant, s'il échoit -- qui leur convient. Tu peux donc utiliser cette particularité pour créer un type d'itérateur particulier pour ta propre classe sous une forme sans doute proche deNote que, si tu décidais d'utiliser une std::list, cela deviendrait simplement
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 class MaClass{ public: // C++11 inside using iterator = typename std::vector<std::string>::iterator; using const_iterator = typename std::vector<std::string>::const_iterator; /* ... */et qu'il en irait de même pour n'importe quelle collection que tu voudrais utiliser.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 class MaClass{ public: // C++11 inside using iterator = typename std::vector<std::string>::iterator; using const_iterator = typename std::vector<std::string>::const_iterator; /* ... */
A partir de là, il faut voir ce que tu veux réellement pouvoir faire. Peut être souhaites-tu vouloir parcourir l'ensemble des chaines de caractères de la collection, du début à la fin? Pas de problème : on rajoute les fonctions begin() et end() qui invoquent les fonctions respectives de la collection utilisée sous une forme proche de
Là, tu commences à obtenir une encapsulation correcte, car la notion d'itérateur (qui est la seule notion dont l'utilisateur de la classe ait réellement besoin ) vient de la classe MaClasse et non de la collection qui permet à MaClasse de maintenir les chaines de caractères!
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 class MaClass{ public: // C++11 inside using iterator = typename std::vector<std::string>::iterator; using const_iterator = typename std::vector<std::string>::const_iterator; /* ... */ const_iterator begin() const{ return items_.begin(); } const_iterator end() const{ return items_.end(); } // et si on veut pouvoir modifier les chaines de caractères, ce que je ne conseille cependant pas // on peut rajouter iterator begin() { return items_.begin(); } iterator end() { return items_.end(); } private: std::vector<std::string> items_;
Au final, tu aurais une classe ressemblant sans doute à quelque chose comme
qui pourrait parfaitement être utilisée sous une forme proche de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 class MaClass{ public: // C++11 inside using const_iterator = typename std::vector<std::string>::const_iterator; /* ... */ const_iterator begin() const{ return items_.begin(); } const_iterator end() const{ return items_.end(); } void add(std::string const & toAdd){ // un nom plus adapté est peut etre préférable :D items_.push_back(toAdd); } // il est toujours intéressant de pouvoir vérifier si // une donnée existe :D bool exists(std::string const & toFind) const{ // C++11 inside for(auto const & it : items_){ if(it == toFind) return true; } return false; private: std::vector<std::string> items_;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 int main(){ MaClasse obj std::string str; do{ std::cin>>str; obj.add(str); while(str != ""); //C++11 inside for(auto const &it : MaClass){ std::cout<<it<<"\n"; } return 0; }
Partager