IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Créer une fonction qui renvoie un vecteur


Sujet :

Langage C++

  1. #21
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    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 de
    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;
           /* ... */
    Note 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.

    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
    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_;
    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!

    Au final, tu aurais une classe ressemblant sans doute à quelque chose comme
    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_;
    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
     
    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;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  2. #22
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 218
    Points : 55
    Points
    55
    Par défaut
    Ok je viens de saisir l'idée. Merci

  3. #23
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Comme d'habitude, un bon cours de Koala, et ça passe tout de suite mieux.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 8
    Dernier message: 24/03/2010, 14h01
  2. Comment faire une fonction qui renvoi un tableau.
    Par poly128 dans le forum Delphi
    Réponses: 2
    Dernier message: 01/06/2006, 01h04
  3. Réponses: 12
    Dernier message: 23/03/2006, 14h13
  4. [9i] PLS-00320 avec une fonction qui renvoi un curseur
    Par hoaxpunk dans le forum Oracle
    Réponses: 5
    Dernier message: 09/02/2006, 17h04
  5. [VB6] Comment faire une fonction qui renvoie 2 résultats
    Par tazarine dans le forum VB 6 et antérieur
    Réponses: 10
    Dernier message: 15/01/2004, 00h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo