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

 C++ Discussion :

Usage des pointeurs dans un objet


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 34
    Points : 46
    Points
    46
    Par défaut Usage des pointeurs dans un objet
    Bonsoir,
    j'ai des difficultés à obtenir un code fonctionnel qui consiste à remplir un simple vector en utilisant le pointeur (membre private de ma classe ) qui pointe dessus.
    Voilà mon code:


    Le fichier flux.h
    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
     
    #include <iostream>
     
     
    #include <vector>
     
     
     
    class img_stream {
        public:
            img_stream();
            ~img_stream();
     
            void fill_stream(int img);
     
            void cout_stream();
     
        private:
            std::vector<int>* img_queue;
     
    };

    Le fichier flux.cpp
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    #include "flux.h"
     
     
     
     
    img_stream::img_stream()
    {
        std::vector<int>* img_queue = new std::vector <int> (0) ; //On crée un tableau vide
     
    }
     
     
    img_stream::~img_stream()
    {    
    }
     
    void img_stream::fill_stream(int img){
       unsigned int size = static_cast<int>(this->img_queue->vector::size());
       std::cout << size << std::endl;
       while(size < 2){                                            //Initialement, j'avais utilisé le while en comparant directement la valeur de img_queue->size() mais cela affichait une erreur 
       this->img_queue->vector::push_back(img);   // car size() serait constant.
       size +=4;
       }
     
    }
     
     
     
    void img_stream::cout_stream()
    {
     
        for(std::vector<int>::iterator it = this->img_queue->begin(); it!=this->img_queue->end(); it++){
        std::cout << *it << std::endl;
        }

    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
     
     
     
    Le fichier main.cpp:
     
    #include "flux.h"
    #include <vector>
     
     
     
    int main(){
     
     
        img_stream flux ;
     
        int T = 3;
     
        flux.img_stream::fill_stream(T);
     
        flux.img_stream::cout_stream();
     
    }
    Je ne suis pas à l'aise avec les pointeurs et je ne parviens pas à comprendre ce que la console affiche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    4253334149              \\Je m'attendais à trouver 2 ici       
    Erreur de segmentation
    En ce qui concerne l'erreur de segmentation voilà ce que j'obtiens avec valgrind:
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    !Damien@Damien-ThinkPad-X200:~/Documents/projet$ valgrind ./a.out --leak-check=full      
    ==7998== Memcheck, a memory error detector
    ==7998== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
    ==7998== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
    ==7998== Command: ./a.out --leak-check=full
    ==7998== 
    ==7998== Use of uninitialised value of size 8
    ==7998==    at 0x401034: std::vector<int, std::allocator<int> >::size() const (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400E3B: img_stream::fill_stream(int) (in /home/Damien/Documents/projet /a.out)
    ==7998==    by 0x400CA1: main (in /home/Damien/Documents/projet/a.out)
    ==7998== 
    ==7998== Use of uninitialised value of size 8
    ==7998==    at 0x40103F: std::vector<int, std::allocator<int> >::size() const (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400E3B: img_stream::fill_stream(int) (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400CA1: main (in /home/Damien/Documents/projet/a.out)
    ==7998== 
    4253334149
    ==7998== Use of uninitialised value of size 8
    ==7998==    at 0x40159C: __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::__normal_iterator(int* const&) (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x4010E7: std::vector<int, std::allocator<int> >::begin() (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400EA9: img_stream::cout_stream() (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400CAD: main (in /home/Damien/Documents/projet/a.out)
    ==7998== 
    ==7998== Use of uninitialised value of size 8
    ==7998==    at 0x40159C: __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::__normal_iterator(int* const&) (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x401133: std::vector<int, std::allocator<int> >::end() (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400EBC: img_stream::cout_stream() (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400CAD: main (in /home/Damien/Documents/projet/a.out)
    ==7998== 
    ==7998== Invalid read of size 4
    ==7998==    at 0x400EE4: img_stream::cout_stream() (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400CAD: main (in /home/Damien/Documents/projet/a.out)
    ==7998==  Address 0x41ff894156415741 is not stack'd, malloc'd or (recently) free'd
    ==7998== 
    ==7998== 
    ==7998== Process terminating with default action of signal 11 (SIGSEGV)
    ==7998==  General Protection Fault
    ==7998==    at 0x400EE4: img_stream::cout_stream() (in /home/Damien/Documents/projet/a.out)
    ==7998==    by 0x400CAD: main (in /home/Damien/Documents/projet/a.out)
    ==7998== 
    ==7998== HEAP SUMMARY:
    ==7998==     in use at exit: 72,728 bytes in 2 blocks
    ==7998==   total heap usage: 3 allocs, 1 frees, 73,752 bytes allocated
    ==7998== 
    ==7998== LEAK SUMMARY:
    ==7998==    definitely lost: 24 bytes in 1 blocks
    ==7998==    indirectly lost: 0 bytes in 0 blocks
    ==7998==      possibly lost: 0 bytes in 0 blocks
    ==7998==    still reachable: 72,704 bytes in 1 blocks
    ==7998==         suppressed: 0 bytes in 0 blocks
    ==7998== Rerun with --leak-check=full to see details of leaked memory
    ==7998== 
    ==7998== For counts of detected and suppressed errors, rerun with: -v
    ==7998== Use --track-origins=yes to see where uninitialised values come from
    ==7998== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
    Erreur de segmentation
    Merci d'avance de votre aide!

    Cordialement.

  2. #2
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 696
    Points : 2 437
    Points
    2 437
    Par défaut
    Bonjour.

    Quand tu écris ce constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    img_stream::img_stream()
    {
        std::vector<int>* img_queue = new std::vector <int> (0) ; //On crée un tableau vide
     
    }
    Tu ne modifies absolument pas la variable membre img_queue mais tu en créés une nouvelle (et tu créés une fuite mémoire) !
    Tu pourrais juste supprimer la partie std::vector<int>* mais pourquoi diable passer par un pointeur de vector alors que ça n'a aucun intérêt ici ?

    Utilise un simple vector comme variable membre et ça irait mieux.
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 34
    Points : 46
    Points
    46
    Par défaut
    Bonjour,
    merci pour la réponse, en effet sous l'ide le "nouveau" img_queue était souligné en vert mais je n'y avais pas prêté attention...

    En ce qui concerne le pointeur vers le vector, je l'utilise car j'ai d'autres classes dans mon programme qui copient l'adresse de ce pointeur pour accéder au tableau.

    Cordialement.

  4. #4
    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
    Salut,
    Citation Envoyé par Gwynbleidd Voir le message
    Bonjour,
    merci pour la réponse, en effet sous l'ide le "nouveau" img_queue était souligné en vert mais je n'y avais pas prêté attention...

    En ce qui concerne le pointeur vers le vector, je l'utilise car j'ai d'autres classes dans mon programme qui copient l'adresse de ce pointeur pour accéder au tableau.

    Cordialement.
    Humm... mauvaise idée...

    Tu as placé ton tableau dans l'accessibilité privée de ta classe. Cela signifie, en gros, que tu as décidé "ce tableau, il appartient aux instances de la classes, et à elles seules".

    Et, après, tu décides que "ben, non, tout comptes faits, on va partager ce tableau avec d'autres classes, dont on ignore tout", ce qui va -- très clairement -- à l'encontre de ta décision d'origine.

    Alors, de deux choses l'une: ou bien ta décision d'origine était sensée, et les autres classes n'ont pas à aller chipoter à ton tableau, ou bien tu as pris une mauvaise décision à l'origine, et ce tableau doit se trouver "quelque part" d'où l'on pourra s'assurer que "tout ce qui y accède" le fait dans les règles.

    Dans le deuxième cas de figure, plutôt que de fournir un pointeur vers le tableau, pourquoi ne pas le transmettre comme paramètre aux seules fonctions qui en ont besoin, voire, si une classe ne peut exister sans en disposer, en créer un membre sous forme de référence
    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

  5. #5
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Si par le plus grand des hasards une autre classe a besoin de récupérer le pointeur d'un membre, c'est exactement pour ça qu'il existe un opérateur & qui permet de récupérer un pointeur.
    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.

  6. #6
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 34
    Points : 46
    Points
    46
    Par défaut
    Bonsoir,
    effectivement ce n'est pas très propre...
    Je souhaite garder mon tableau uniquement modifiable par mes classes qui pourront en copier le pointeur: le tableau ne serait pas accessible en dehors des classes.
    Donc, il faut que je leur donne un moyen d'y accéder.

    Par contre, je ne comprends pas la notion de passage par référence d'un membre de classe (je comprends quand il s'agit d'une fonction mais pas dans ce cas ci): pourriez vous donner un petit exemple s'il vous plaît?

    Enfin, dernière question : Si on passe par référence le membre de la classe, cela revient à faire la même sorte de "bidouillage" qu'en copiant des adresses mémoires non? Je ne comprends pas vraiment pourquoi on préférerait les références aux pointeurs si c'est pour aboutir à un résultat similaire.

    Cordialement.

  7. #7
    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
    En fait, les autres classes ne veulent pas accéder au tableau... Elles veulent accéder au contenu du tableau, sous une forme constante, ou non.

    Le plus facile est donc de leur fournir le moyen d'accéder à ce contenu, par exemple:
    1. en fournissant la notion d'itérateur et les fonctions begin() et end() que l'on retrouve dans n'importe quelle collection de la bibliothèque standard
    2. en fournissant une fonction size() qui permette de connaitre le nombre d'éléments et un opérateur ( () [] autre ) ou une fonction qui permette d'accéder à l'élément souhaité.

    le (1) pourrait prendre 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
    26
    27
    class img_stream {
        public:
            /* deux alias de type permettant d'écrire un code proche de  
             * img_stream::iterator it /  img_stream::const_iterator it
             * sans que l'utilisateur ne doive avoir conscience de manipuler des
             * ... std::vector<int> /*const_*/iterator
             */ 
            using iterator = typename std::vector<int>::iterator;
            using const_iterator = typename std::vector<int>::const_iterator;
            /* les fonctions "begin" et "end" classiques */
            iterator begin() {
                return img_queue.begin();
            }
            iterator end {
                return img_queue.end();
            }
            const_iterator begin() const{
                return img_queue.begin();
            }
            const_iterator end() const{
                return img_queue.end();
            }
     
        private:
            std::vector<int> img_queue;
     
    };
    le (2) pourrait prendre 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
    class img_stream {
        public:
            int & operator()(size_t index){
                assert(index < img_queue.size() && "index out of bound");
                return img_queue[index];
            }
            int operator()(size_t index) const{
                return const_cast<img_stream &>(*this).operator()(index);
            }
     
        private:
            std::vector<int> img_queue;
     
    };
    (les deux solutions ne sont pas incompatibles )
    Par contre, je ne comprends pas la notion de passage par référence d'un membre de classe (je comprends quand il s'agit d'une fonction mais pas dans ce cas ci): pourriez vous donner un petit exemple s'il vous plaît?
    Plutot que d'avoir une donnée membre qui représente un pointeur vers le tableau de cette classe ci dans "une autre classe", transmet aux fonctions de "cette autre classe" qui en ont besoin une référence (de préférence constante) sur le tableau de la classe, exactement comme tu le ferais pour une fonction libre.

    Voire, si tu rajoute les fonctions dont je viens de fournir l'exemple, transmet carréement ton instance de img_stream sous forme d'une référence (de préférence constante) à ces fonctions. Elle n'auront qu'à appeler les fonctions "qui vont bien" de ta classe img_stream
    Enfin, dernière question : Si on passe par référence le membre de la classe, cela revient à faire la même sorte de "bidouillage" qu'en copiant des adresses mémoires non? Je ne comprends pas vraiment pourquoi on préférerait les références aux pointeurs si c'est pour aboutir à un résultat similaire.
    Techniquement parlant, si tu regarde au niveau du code binaire qui sera généré, oui, effectivement, cela reviendra exactement au même.

    Mais la notion de référence subit des restrictions auxquelles les pointeurs ne sont pas soumis. Et ces restrictions (susceptibles d'être vérifiées par le compilateur) sont de nature à augmenter énormément la qualité de ton code, même si la technique reste "cra cra". Les deux principaux attraits sont:
    1. L'objet référencé par une référence doit exister, alors qu'un pointeur est toujours susceptible de pointer sur une adresse invalide (qu'elle soit connue comme telle ou non). Tout ce qu'il faut donc faire, c'est s'assurer que l'objet référencé existera bel et bien aussi longtemps que la référence existera. Mais il n'y a plus le moindre problème à partir du principe que c'est le cas (plus besoin de vérifier si le pointeur pointe vers une adresse valide, au risque qu'il ne fasse que "laisser croire" que c'est le cas)
    2. Le compilateur a beaucoup plus facile à garantir la const-correctness d'une référence: si tu as une référence constante, tu pourras danser sur ta tête: tout ce qui pourrait risquer de modifier l'état de l'objet référencé sera refusé par le compilateur, et ca, c'est une garantie forte que tu ne feras pas de bêtises

    Alors, bien sur, je reste sur ma position quant au fait qu'il y a "un problème" avec ton point de vue. Mais, tant qu'à faire, je préférerais que tu utilises des références (voir des std::reference_wrapper pour les cas les plus complexes) plutôt que des pointeurs
    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

  8. #8
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 34
    Points : 46
    Points
    46
    Par défaut
    Bonjour,
    mes remerciements chaleureux pour ce message, voilà que tout s'éclaire !

    C'est vrai qu'il est plus propre et moins fastidieux de passer par des références, on s'enlève une sacrée dose de travail !

    Je reconnais qu'il y a un problème avec ce que je veux faire, mais le programme risque d'être assez volumineux, donc ici, je préfère avoir une structure un petit alambiquée pour pouvoir bien dissocier les différentes parties de mon programme.

    Merci beaucoup, je passe le sujet en résolu!

    Cordialement.

  9. #9
    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
    Citation Envoyé par Gwynbleidd Voir le message
    Bonjour,
    mes remerciements chaleureux pour ce message, voilà que tout s'éclaire !

    C'est vrai qu'il est plus propre et moins fastidieux de passer par des références, on s'enlève une sacrée dose de travail !

    Je reconnais qu'il y a un problème avec ce que je veux faire, mais le programme risque d'être assez volumineux, donc ici, je préfère avoir une structure un petit alambiquée pour pouvoir bien dissocier les différentes parties de mon programme.

    Merci beaucoup, je passe le sujet en résolu!

    Cordialement.
    Re voilà une très mauvaise idée...

    Comme dirait Einstein: il faut rendre les choses aussi simples que possibles, mais guère plus!

    Tu dois prendre le parti de ne penser qu'à la notion que tu développes au moment où tu la développes, et de ne pas t'inquiéter de ce qui "viendra plus tard", de manière à pouvoir créer tes notions sous leur forme la plus simple.

    Il faut, bien sur, prendre les évolutions prévisibles en compte, en prévoyant des "points de variation" (dans les respect du DIP, entre autres), mais tu dois -- surtout -- t'assurer que chaque notion qui prendra la forme d'un type dans ton code soit en mesure de rendre les services auxquels on est en droit de s'attendre de sa part. Ni plus, ni moins; et en restant "aussi simple qu'il est possible de l'être".

    Il n'y a que de cette manière que tu arriveras au final à intégrer les différentes évolutions sans ** trop ** te casser la tête, sans "casser" quelque chose qui fonctionne pour y arriver et sans devoir "tout jeter" car ton code est inadapté à l'évolution que tu veux ajouter

    Tu sais, on peut généralement subdiviser la complexité d'un projet en deux parties: la partie inhérente au domaine de l'application en elle-même, du projet en lui-même et la partie qui n'est due qu'à de mauvaises décisions prises en des temps qui n'étaient pas opportuns:

    Rien n'est plus source de complexité, par exemple, qu'un héritage qui n'aurait pas lieu d'être car il ne respecte pas le SRP, ou qu'un code qui ne respecte pas l'OCP.

    Or, ton projet -- n'importe quel projet -- est déjà "assez complexe comme cela", en raison de toutes les contraintes auxquelles sont soumises les différentes données et à cause des manipulations qu'elles doivent subir.

    Et il est vain d'estimer que, en rajoutant de la complexité qui n'a pas lieu d'être, tu arriveras à te faciliter la tâche par la suite: on ne fait pas du simple avec du compliqué; on fait du simple avec du simple
    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

  10. #10
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 34
    Points : 46
    Points
    46
    Par défaut
    Bonjour,
    j'avoue avoir un peu de mal à comprendre.
    Est ce en soi une mauvaise idée d'avoir des membres private qui puissent être accédés par d'autres classes mais qui soient inaccessibles directement depuis le main()? je fais le choix de ne pas les mettre public pour ne pas qu'on puisse y avoir accès de partout mais je ne veux pas non plus empêcher toute interaction avec ces membres.

    Y aurait-il une alternative à cela?

    Cordialement.

  11. #11
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Est ce en soi une mauvaise idée d'avoir des membres private qui puissent être accédés par d'autres classes mais qui soient inaccessibles directement depuis le main()?
    Comme toujours, cela dépend, c'est pas forcément une mauvaise idée. C'est juste presque toujours une mauvaise idée

    Si tu autorises plusieurs classes à avoir accès aux données membres d'une autre classe X, tu commences à instaurer une relation de dépendance importante entre ces différentes classes. Que le main y ait accès ou non n'a pas beaucoup d'importance : ce qui est important c'est de savoir combien de classes ne fonctionneront plus le jour où tu modifieras par exemple le type des données membres de la classe X (ce problème de dépendance deviendra d'autant plus important que ton code est volumineux, donc que tu as de classes qui interagissent).

    La solution habituelle reste de planquer tes données (= détails d'implémentation) derrière des interfaces claires (= services de la classe) qui s'avèreront à la longue plus solides, plus résistantes aux évolutions. En effet la représentation des données que l'on manipule est assez instable (par exemple "je vais finalement utiliser une std::list plutôt qu'une std::vector") et non pas tant la manière de les manipuler (par exemple "list ou vector dans tous les cas je veux le premier élément"). Autrement dit, les données membres auront tendance à être plus sujets au changement que les fonctions que l'on appelle dessus (c'est pour ça qu'on les appelle justement des détails d'implémentation).

    En général quand tu stockes des données à un endroit c'est pour travailler dessus, y appeler des traitements. Donc le plus simple reste de rassembler ces traitements au même endroit (donc dans la classe). De cette manière, chaque classe représentera un ensemble de services que tu peux considérer, manipuler, tester relativement indépendamment les uns des autres. Et ce sera très confortable le jour où ton projet sera passé de 3 classes/200 lignes à 100 classes/6000 lignes : en effet tu pourras modifier l'intérieur de la classe X sans que cela ne fasse planter les 15 classes qui gravitent autour de X, parce que tu auras veillé à ce que ces 15 classes utilisent les services de X, au lieu de se contenter d'accéder à ses données
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  12. #12
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2016
    Messages : 34
    Points : 46
    Points
    46
    Par défaut
    Bonjour,
    merci pour la réponse, je comprends mieux maintenant, je vais tâcher de lui donner la structure la plus propre possible en me servant de toutes vos recommandations!

    Cordialement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Usage des pointeurs dans les fonctions
    Par didou31 dans le forum Débuter
    Réponses: 12
    Dernier message: 22/11/2011, 13h31
  2. Ajouter des données dans un objet Listbox
    Par nuans dans le forum Interfaces Graphiques
    Réponses: 11
    Dernier message: 23/05/2007, 11h49
  3. Réponses: 2
    Dernier message: 21/02/2007, 13h28
  4. Ecrire des valeurs dans un objet OLE Excel
    Par NewbiePower dans le forum Access
    Réponses: 4
    Dernier message: 08/02/2007, 08h59
  5. Libérer des pointeurs dans une std::map
    Par GaldorSP dans le forum SL & STL
    Réponses: 2
    Dernier message: 09/07/2005, 14h42

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