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. #1
    Membre confirmé
    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
    Par défaut Créer une fonction qui renvoie un vecteur
    Bonjour,

    J'essaye en vain de faire un accesseur pour un vecteur d'une classe. J'ai fait des accesseurs pour tous les attributs de ma classe mais je n'arrive pas à faire celui du vecteur. J'utilise Qt mais à prioris ça n'a pas d'incidence sur mon problème. Je précise que j'ai cherché déjà plein d'exemples sur le net et qu'ils ne marchent pas chez moi, inutile de m'accabler de reproches.

    voici la déclaration dans le .h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<QString> genres[5];
     
    const std::vector<QString> &getGenres();
    et dans le .cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const std::vector<QString>& Film::getGenres()
    {
        return genres;
    }
    C'est la copie conforme d'un des exemples que j'ai trouvé mais il me renvoie l'erreur: invalid initialization of reference of type 'const std::vector<QString>&' from expression of type 'const std::vector<QString>*'
    Au passage, est-ce que vous pouvez me donner le code pour faire un Set pour modifier les valeurs du vecteurs?
    Merci d'avance.

    Cordialement

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Bonjour

    Remplace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<QString> genres[5];
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<QString> genres;
    Le deuxième est un tableau (taille dynamique) de QString.
    Le premier est un tableau (taille fixe à 5) de tableau (taille dynamique) de QString.

    Si ta méthode ne modifie pas l'objet, tu "dois" l'indiquer :
    Remplace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const std::vector<QString> &getGenres()
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<QString> const & getGenres() const
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const std::vector<QString> &getGenres()
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<QString> const & Film::getGenres() const
    PS: Utilise la balise [CODE]

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Maintenant que l'on t'a donné la solution, je tiens quand meme à insister sur le fait que, à mon sens, tu ne devrais pas prévoir un accesseur sur ton vecteur de Qstring, pas plus que tu ne devrais prévoir un mutateur (que je subodore que tu as aussi prévu) d'ailleurs!

    Ce que tu aurais très largement intérêt à faire, c'est de réfléchir aux services que tu es en droit d'attendre de la part des ta classes qui sont en rapport avec la présence de ce tableau.

    Car il existe une règle érigée en loi qui s'appelle la loi de Déméter qui nous dit que, si un objet de type A (ta classe Film) utilise en interne un objet de type B(le std::vector<QString>), l'utilisateur de la classe A (la classe Film) ne devrait pas avoir à connaître la classe B pour pouvoir utiliser son objet de type A.

    C'est encore plus vrai pour tout ce qui a trait aux conteneurs : Typiquement, il ne devraient servir qu'au maintient en interne des données utilisées par la ta classes
    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

  4. #4
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    Rien n'empêche, par contre, de prévoir un itérateur... si c'est dans le sens réel de la classe. (en ce cas, prévoir a la fois begin() et end(), et un ++)

    L'itérateur masque le vecteur, sans cacher la sémantique de collection de genres.

  5. #5
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Bonsoir,
    Citation Envoyé par leternel Voir le message
    L'itérateur masque le vecteur, sans cacher la sémantique de collection de genres.
    Excusez moi, mais en quoi l'iterateur masquerait-il le vecteur ? Pour appeler un iterateur, on est obliger de specifier son conteneur non ? (à part peut être pour le c++11 avec auto ?)

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 154
    Billets dans le blog
    4
    Par défaut
    Non parce que tu itères sur les objets contenus dans la collection, quelle que soit la colletion.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Membre confirmé
    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
    Par défaut
    Mon problème est résolu, le code marche. En fait j'avais déjà essayé le code mais il n'avait pas marché. J'ai fermé puis réouvert QtCreator et là ça a marché sans buguer -_-'
    Merci pour vos réponses. Concernant la loi de Déméter, cela voudrait-il dire qu'il ne faut pas utiliser de vecteur dans une classe? Car il se trouve que c'est exactement ce qu'il me faut. A ce moment là, (je compare avec Java où tous les types sont des objets) cela voudrait dire qu'il ne faut pas utiliser de int, QString etc... dans une classe? J'avoue ne pas très bien saisir cette remarque.

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Avatar36 Voir le message
    Mon problème est résolu, le code marche. En fait j'avais déjà essayé le code mais il n'avait pas marché. J'ai fermé puis réouvert QtCreator et là ça a marché sans buguer -_-'
    Merci pour vos réponses. Concernant la loi de Déméter, cela voudrait-il dire qu'il ne faut pas utiliser de vecteur dans une classe? Car il se trouve que c'est exactement ce qu'il me faut. A ce moment là, (je compare avec Java où tous les types sont des objets) cela voudrait dire qu'il ne faut pas utiliser de int, QString etc... dans une classe? J'avoue ne pas très bien saisir cette remarque.
    Non, cela veut juste dire que ton vecteur doit être correctement encapsulé et que l'utilisateur de ta classe n'a pas à savoir que tu utilise un std::vector, un QList, un tableau de taille fixe ou un tableau de taille dynamique géré à la main.

    Ce genre d'information correspond typiquement à ce que l'on appelle un détail d'implémentation! La solution consiste à fournir "tout ce qu'il faut" à l'utilisateur de la classe pour qu'il puisse l'utiliser sans avoir besoin de s'inquiéter de ces détails. Par exemple :
    • un alias sur le type d'itérateur utilisé par la collection te permettant de fournir les fonctions begin, end et find, si cela s'avere utile
    • une fonction addXXX (nom à adapter) permettant de rajouter une information dans la collection
    • d'autres fonctions en rapport avec la présence de la collection, en fonction des besoins queta classe doit satisfaire
    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

  9. #9
    Membre confirmé
    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
    Par défaut
    Merci pour cette réponse. C'est on ne peut plus clair il me semble. C'est bien de la manière dont j'ai procédé.

    Cordialement

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Heuu... j'ai juste oublié une chose importante : à aucun prix il ne faut un getVector() ou un setVector(std::vector<> const &) !!!!

    Et j'ai l'impression que tu as, justement, fourni ces deux fonctions
    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

  11. #11
    Membre confirmé
    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
    Par défaut
    C'est effectivement ce que j'ai fait. Mais quel est le problème du coup? Et comment puis récupérer mon vecteur alors? Car mon but est effectivement de renvoyer un tableau dynamique. Dans mon cas c'est pour ranger les acteurs d'un film. Et comme il n'y a pas forcément le même nombre d'acteurs entre un film et un autre, un tableau dynamique me semblait adapté. Mais pour ça je suis obligé de le stocker dans mon objet "film".

  12. #12
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    Le film n'a pas à proposer à un utilisateur de trier l'ordre de ses auteurs.
    C'est une propriété interne.

    Un film ne changeant pas d'auteur une fois réalisé, il ne devrait y avoir que des constructeurs et des fonctions de lecture.
    Inspire-toi de <algorithm> pour l'usage des itérateurs dans le constructeur

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 154
    Billets dans le blog
    4
    Par défaut
    C'est effectivement ce que j'ai fait. Mais quel est le problème du coup? Et comment puis récupérer mon vecteur alors?
    Quelle est la plus-value d'une classe avec SetVector et GetVector plutôt que de manipuler directement le vector en question ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  14. #14
    Membre confirmé
    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
    Par défaut
    Et bien c'était pour respecter l'encapsulation
    Sans ça tout serait public. Concernant l'ordre, à vrai dire je n'y accordais pas d'importance. Je souhaitais que le logiciel aille récupérer des infos sur internet et remplirait donc tout seul ces cases. Mais même si les infos sont rentrées à la main, elles seront enregistrées dans l'ordre dans lequel elles seront rentrées. Je ne comprends pas bien le problème. De plus, si le logiciel récupère les mauvaises infos ou n'importe quoi d'autre, l'utilisateur doit être en mesure de corriger les erreurs. D'où ma volonté de faire un modificateur pour chaque variable.

  15. #15
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par Avatar36 Voir le message
    Et bien c'était pour respecter l'encapsulation
    Sans ça tout serait public.
    Si tu as un getter et un setter pour un attribut, autant le mettre public.

    Tu peux permettre de modifier un élément du vecteur, sans pour autant exposer le vecteur.
    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
    class Foo {
       std::vector<int> m_vec;
     
    public:
       void add(int val) { m_vec.push_back(val); }
     
       void data(int ind, int val) { m_vec.at(ind) = val; }
       int data(int ind) const { return m_vec.at(ind); }
       int& data(int ind) { return m_vec.at(ind); }
    };
     
    Foo f;
    for(int i=0; i<5; ++i) { f.add(i); } // ajoute 5 éléments
    std::cout << f.data(1); // affiche le 2eme élément du vector
    f.data(2, 10); // set le 3eme élément à 10
    f.data(3) = 42; // set le 4eme élément à 42

  16. #16
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    Globalement, l'encapsulation ce n'est pas "les attributs sont privés", mais un principe plus large.
    Du point de vue de la classe, ça ressemble à "je dis ce que je peux faire, pas comment".

    La partie publique d'une classe est plus orienté "métier" que la partie privée, plus haut niveau.

    Le std::vector<std::string> est un détail, les auteurs sont utiles.
    Pour des raisons de performance, tu pourrais vouloir remplacer le vector par une liste, un arbre ou un zergling, ca ne doit impacter ni l'utilisation de la classe, ni même sont interface publique.

    Pour le protégé c'est un peu plus négociable, même si je préfère personnellement le laisser invariant.

  17. #17
    Membre confirmé
    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
    Par défaut
    Dans un cours sur un site, il est écrit en gros que tous les attributs d'une classe doivent être privés. Le risque étant que sinon on peut appeler la variable de la classe sans le vouloir. Même si je suis d'accord que dans mon cas tout public ou non ça revient au même sauf que je ne risque pas de modifier mes attributs du film sans le vouloir. Et si je suis ton exemple avec le vecteur, je vois pas trop la différence avec moi. Si tu remplace Foo par Films et tu rajoutes les attributs du films, tu as à peu près le même code que moi . Ou alors c'est moi qui ai pas vu la différence.

  18. #18
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 154
    Billets dans le blog
    4
    Par défaut
    Et bien c'était pour respecter l'encapsulation
    Une encapsulation qui n'apporte rien, c'est inutile.

    A partir du moment où tu as un setter aussi explicite qui remplace le membre, c'est strictement équivalent.
    Je pense pas qu'il faille être beaucoup plus stupide pour écrire maClass.SetVector(monVector); que maClass.vector = monvector;. Donc le risque d'appeler la variable sans le vouloir..
    Commençons par utiliser la const-correctness et ça arrivera moins.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  19. #19
    Membre confirmé
    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
    Par défaut
    Ben c'est quand même bien quand on part de zero. Mais après cela s'adresse à de vrai débutants et il est vrai que quand on partage le code, il vaut certainement mieux respecter cette règle pour éviter les conflits donc le faire tout le temps n'est pas mal, c'est simplement plus lourd. Mais effectivement dans mon cas c'est inutile. De manière générale je pense pas que ce soit très utile quand on est seul à travailler sur un projet. En tout cas merci, ça m'a pas mal éclairé. Petit à petit je m'approcherai d'un code propre et clair.

  20. #20
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par Avatar36 Voir le message
    Et si je suis ton exemple avec le vecteur, je vois pas trop la différence avec moi. Si tu remplace Foo par Films et tu rajoutes les attributs du films, tu as à peu près le même code que moi . Ou alors c'est moi qui ai pas vu la différence.
    Il y à une différence majeure :
    Imaginons que demain tu ai besoin d'utiliser un autre type de conteneur, une list, ou une map par exemple, l'utilisation reste identique : seul le code de la classe change.
    Tu n'as donc pas à savoir quel type Foo (ou Film) manipule en interne.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 8
    Dernier message: 24/03/2010, 15h01
  2. Comment faire une fonction qui renvoi un tableau.
    Par poly128 dans le forum Delphi
    Réponses: 2
    Dernier message: 01/06/2006, 02h04
  3. Réponses: 12
    Dernier message: 23/03/2006, 15h13
  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, 18h04
  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, 01h13

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