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 :

Constructeur de copie et tableau d'objet.


Sujet :

C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2013
    Messages : 5
    Points : 3
    Points
    3
    Par défaut Constructeur de copie et tableau d'objet.
    Bonjour tout le monde !

    Je suis nouveau sur le forum et débutant en C++. J'ai besoin d'aide sur mon programme.

    Je vous mets d'abord quelques parties de mon code
    Voici ma classe "Plateau":

    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
    class Plateau
    {
        public :
     
            Plateau ();
            Plateau (int h=21, int l=51);
            Plateau(Plateau const& copiePlateau); // Constructeur de copie
            Plateau& operator=(Plateau const& copiePlateau);
            ~Plateau();
            void affiche();
            void affiche_fichier();
            int getLargeur() const;
     
        private :
     
            int hauteur;
            int largeur;
            Etat **tab;
     
    };
    Mon problème , c'est comment implémenter le constructeur par copie et la méthode "operator=" avec tableau d'objet pareil ??
    J'ai essayé plusieurs et fait quelques recherches mais je trouve pas.
    Voici quelques implémentations de mes constructeurs:
    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
     
    Plateau::Plateau () : hauteur(21), largeur(51), tab(0)
    {
        tab = new Etat*[hauteur];
        for (int i=0; i < hauteur; i++)
            tab[i] = new Etat [largeur];
     
    }
    Plateau::Plateau (int h, int l) : hauteur(h), largeur(l)
    {
        if ((hauteur > 0 && largeur > 0) || (hauteur % 2 != 0 && largeur % 2 != 0))
        {
            tab = new Etat*[hauteur];
            for (int i=0; i < hauteur; i++)
                tab[i] = new Etat [largeur];
                }
        else
        {
            hauteur = 21;
            largeur = 51;
            tab = new Etat*[hauteur];
            for (int i=0; i < hauteur; i++)
                tab[i] = new Etat [largeur];
     
        }
     
    }
     
    Plateau::Plateau (Plateau const& copiePlateau) : hauteur(copiePlateur.hauteur), largeur(copiePlateau.largeur), tab(0)
    {
        tab = new Etat (*(copiePlateau.tab));
    }
     
    Plateau& Plateau::operator=(Plateau const& copiePlateau)
    {
        if (this != &copiePlateau)
        {
            hauteur = copiePlateau.hauteur;
            largeur = copiePlateau.largeur;
            delete tab;
     
     
        }
        return *this;
    }
     
    Plateau::~Plateau()
    {
        for (int i=0; i < hauteur; i++)
            delete tab[i];
        delete []tab;
    }
    Vous verrez que j'ai commencé mais j'ai pas pu les finir.
    J'ai aussi eu des idées comme utiliser une boucle pour copier le tableau case par case mais je sais si c'est pratique ou des fonctions comme "memcpy" ou autres.
    Pour les autres méthodes implémentées aussi , si vous voyez des erreurs dites le moi.

    Merci d'avance pour vos réponse.

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 040
    Points
    33 040
    Billets dans le blog
    4
    Par défaut
    Bonsoir,

    prenons le problème inverse : est-il logique, souhaitable et correct de vouloir copier un plateau ?!

    Si oui, la solution triviale en lisant ton code saute aux yeux : il faut copier tous les états.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2013
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Bonsoir

    Merci pour ta réponse , je commençais à désespérer et en même temps c'est pas facile d'avoir une réponse en week-end.

    Je précise que c'est un projet et on m'impose de faire la forme canonique de coplien. Donc j'ai pas trop saisi ce que tu voulais dire par copier tous les états.

    Un peu d'exlications??

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    La première chose qui me saute aux yeux, c'est que les deux lignes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            Plateau ();
            Plateau (int h=21, int l=51);
    poseront forcément un problème.

    En effet, la deuxième ligne permet de rendre la transmission de la hauteur et de la largeur optionnelle et correspond donc à trois constructeurs différents qui prendraient respectivement les formes de Plateau(), Plateau(int h) et Plateau(int h, int l).

    Comme tu peux le constater, la première forme déduite (celle qui prend la valeur par défaut pour la hauteur et la largeur) correspond trait pour trait à la première ligne que j'ai reproduite. Cela ne plaira absolument pas au compilateur sous prétexte d'ambiguité

    En outre, si on peut effectivement considérer comme "cohérent" le fait d'avoir un constructeur ne prenant aucun argument, qui définira donc la hauteur à 21 et la largeur à 51, si on peut effectivement considérer comme cohérent le fait d'avoir un constructeur qui impose à l'utilisateur de définir la hauteur ET la largeur, il ne me semble absolument pas cohérent de permettre à l'utilisateur de définir la hauteur uniquement en utilisant une valeur (51) arbitraire pour la largeur

    Tu devrais donc déjà corriger ce problème, sans doute en définissant Plateau() et Plateau(int h, int l) mais sans donner de valeur par défaut ni pour h ni pour l. Du moins, c'est ce qui me semble le plus cohérent à faire

    La deuxième chose qui pique aux yeux, c'est l'utilisation d'un (signed) int pour la hauteur et la largeur. La hauteur et la largeur ne pourront jamais être négatives, dés lors, pourquoi n'utiliserais tu pas un type connu pour être non signé comme un size_t par exemple

    Cela éviterait à l'utilisateur d'écrire un code qui pourrait ressembler à [CODEinline]Plateau( -5, -10)[CODEinline] et qui n'aurait strictement aucun sens

    La troisième chose qui pique aux yeux, c'est que tu fais, à l'exception de la définition des valeur pour h et pour l, exactement la même chose dans la partie if que dans la partie else du test de Plateau(int h, int l).

    Copier du code n'est jamais une bonne chose, surtout lorsqu'il y a parfaitement moyen de garder une logique exactement similaire sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Plateau::Plateau (int h, int l) : hauteur(h), largeur(l)
    {
        if (!((hauteur > 0 && largeur > 0) || (hauteur % 2 != 0 && largeur % 2 != 0)))
        {
            hauteur = 21;
            largeur = 51;
        }
        tab = new Etat*[hauteur];
        for (int i=0; i < hauteur; i++)
            tab[i] = new Etat [largeur];
    }
    Notes au passage que le fait d'utiliser un entier non signé comme size_t t'aurait évité la peine du premier test sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Plateau::Plateau(size_t h, size_t l) : hauteur(h), largeur(l){
        if (!(hauteur % 2 != 0 && largeur % 2 != 0))
        {
            hauteur = 21;
            largeur = 51;
        }
        tab = new Etat*[hauteur];
        for (int i=0; i < hauteur; i++)
            tab[i] = new Etat [largeur];
    }
    En ce qui concerne ce code, justement, je ne peux pas me résoudre à ne pas te rappeler que, très souvent, lorsque tu veut créer une "matrice" de L lignes par C Colonnes, tu veux en réalité surtout disposer d'une structure capable de représenter L*C éléments.

    Et comme on conseille généralement de n'utiliser les pointeurs que lorsque l'on n'a vraiment pas d'autre choix, tu comprendra que l'on déconseille d'autant plus l'utilisation de pointeurs de pointeur .

    Tu pourrais donc te faciliter la vie (d'autant plus qu'il y a un problème de gestion des exceptions à prendre en compte) et, qui sait, même peut être gagner en performances en allouant un seul tableau de hauteur * largeur éléments de type Etat et en utilisant, si tu veux accéder à un élément particulier, la formule index recherché = Ligne voulue * largeur + colonne recherchéeTa classe pourrait donc ressembler à 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
    class Plateau
    {
        public :
     
            Plateau ();
            Plateau (size_t h, size_t l);
            Plateau(Plateau const& copiePlateau); // Constructeur de copie
            Plateau& operator=(Plateau const& copiePlateau);
            ~Plateau();
            void affiche();
            void affiche_fichier();
            int getLargeur() const;
     
        private :
     
            size_t hauteur;
            size_t largeur;
            Etat *tab;
     
    };
    Quant à l'implémentation des constructeurs, elle ressemblerait à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Plateau::Plateau () : hauteur(21), largeur(51), tab(0)
    {
        tab = new Etat*[hauteur * largeur];
     
    }
    Plateau::Plateau(size_t h, size_t l) : hauteur(h), largeur(l){
        if (!(hauteur % 2 != 0 && largeur % 2 != 0))
        {
            hauteur = 21;
            largeur = 51;
        }
        tab = new Etat*[hauteur * largeur];
    }
    Quant au destructeur, il prendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Plateau::~Plateau(){
        delete [] tab;
    }
    Avoues que ca facilite quand même énormément les choses non

    Au passage, j'espère que Etat est un type qui a sémantique de valeur et qu'il ne s'agit pas d'une classe de base présentant des comportements polymorphes, car, autrement, tu devrais de toutes manières créer une collection de pointeurs sur des objets de type Etat afin de profiter du polymorphisme .

    Tu dois en outre faire attention à ton constructeur de copie. Son but est double:

    1 - Il doit allouer un espace mémoire suffisant pour représenter l'ensemble des données qui se trouve dans l'objet d'origine.

    Si tu tab est un pointeur de pointeurs, tu dois donc suivre exactement la même logique d'allocation dynamique de la mémoire que celle que tu suis dans tes constructeurs (la vérification en moins, vu que tu copies la valeur des membres largeur et hauteur d'un objet existant).

    2 - L'idée est d'avoir un objet qui est la copie conforme de l'objet original. Cela signifie que, chaque état se trouvant sur une ligne et une colonne donnée doit correspondre à l'état se trouvant sur la même ligne et la même colonne de l'objet original.

    Une fois que tu as alloué un espace mémoire suffisant pour représenter l'ensemble des états, tu dois donc veiller à copier les états eux-mêmes
    Avec ton code orignal, ton constructeur par copie prendrait donc la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Plateau::Plateau (Plateau const& copiePlateau) : hauteur(copiePlateur.hauteur), largeur(copiePlateau.largeur), tab(0)
    {
        // 1- on alloue l'espace mémoire nécessaire pour représenter l'ensemble des états
        tab = new Etat*[hauteur];
        for (int i=0; i < hauteur; i++)
            tab[i] = new Etat [largeur];
        // 2 - on copie tous les états de l'objet d'origine 
        for(int ligne = 0; ligne <hauteur; ++ligne){
            for(int colonne = 0; colonne < largeur; ++ colonne){
                tab[ligne][colonne] = copiePlateur[ligne][colonne];
            }
        }
    }
    Avec les modifications que je t'ai proposées pour la classe, il ressemblerait à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Plateau::Plateau (Plateau const& copiePlateau) : hauteur(copiePlateur.hauteur), largeur(copiePlateau.largeur), tab(0)
    {
        // 1- on alloue l'espace mémoire nécessaire pour représenter l'ensemble des états
        tab = new Etat*[hauteur * largeur];
        // 2 - on copie tous les états de l'objet d'origine 
        for(int i = 0; i <hauteur * largeur; ++i){
            tab[i] = copiePlateur[i];
        }
    }
    J'en arrive maintenant à la (quatrième , j'ai un peu perdu le fil :-S) chose qui pique aux yeux : le test d'auto affectation dans l'opérateur d'affectation de ta classe.

    Ce test ne sert strictement à rien. Il est sorti de l'esprit malade d'un tordu qui a posé une question aberrante à laquelle les gens ont essayé tant bien que mal d'apporter une réponse tout aussi aberrante.

    Le plus facile, pour implémenter l'opérateur d'affectation est d'utiliser l'idiome copy and swap: une fois que l'on a fourni une implémentation correcte pour le constructeur de copie et pour le destructeur, on les fait travailler avantageusement pour nous en créant une copie temporaire (qui sera donc détruite lorsqu'on quittera la portée de l'opérateur d'affectation) et en intervertissant les membres un à un entre l'objet modifié et la copie.

    Cela peut se faire sous la forme 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
    Plateau& Plateau::operator=(Plateau const& copiePlateau)
    {
        // 1 - on crée une copie temporaire de copiePlateau (*)
        Plateau temp(copiePlateau);
        // 2 - la hauteur de l'objet en cours devient celle de la copie
        hauteur = temp.hauteur;
        // 3 - la largeur de l'objet en cours devient celle de la copie
        largeur = temp.largeur;
        // 4 - on interverti l'adresse représentée par tab dans l'objet en cours
        //     et celle de tab dans la copie (version pointeur de pointeurs ;) )
        Etat ** ptr(temp.tab);
        temp.tab = tab:
        tab = ptr;
        return *this;
    } // temp est détruit ici, son destructeur est appelé, la mémoire de temp.tab 
      // (qui était à l'origine celle de l'objet courant) est libérée
    On peut d'ailleurs se faciliter la vie en utiliser la fonction std::swap et que l'on trouve dans le fichier d'en-tête <algorithm> ( <utility> en C++11) qui est, justement, faite pour invtervertir les valeurs sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Plateau& Plateau::operator=(Plateau const& copiePlateau)
    {
        // 1 - on crée une copie temporaire de copiePlateau (*)
        Plateau temp(copiePlateau);
        // 2 - la hauteur de l'objet en cours devient celle de la copie
        std::swap(hauteur, temp.hauteur);
        // 3 - la largeur de l'objet en cours devient celle de la copie
        std::swap(largeur, temp.largeur);
        // 4 - on interverti l'adresse représentée par tab dans l'objet en cours
        std::swap(tab, temp.tab):
        return *this;
    } // temp est détruit ici, son destructeur est appelé, la mémoire de temp.tab 
      // (qui était à l'origine celle de l'objet courant) est libérée
    Et le fin du fin serait d'ailleurs de fournir la possibilité d'intervertir le contenu de deux tableaux en exposant directement une fonction swap.

    Sur base de ton code d'origine (auquel je ne modifie que les int en size_t), cela pourrait prendre la forme 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
    class Plateau
    {
        public :
     
            Plateau ();
            Plateau (size_t h, size_t l);
            Plateau(Plateau const& copiePlateau); // Constructeur de copie
            Plateau& operator=(Plateau const& copiePlateau);
            ~Plateau();
            void affiche();
            void affiche_fichier();
            size_t getLargeur() const;
            void swap(Plateau & other);
        private :
     
            size_t hauteur;
            size_t largeur;
            Etat **tab;
    };
    ce qui permettrait de simplifier l'opérateur d'affectation en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Plateau& Plateau::operator=(Plateau const& copiePlateau)
    {
        // 1 - on crée une copie temporaire de copiePlateau (*)
        Plateau temp(copiePlateau);
       // on interverti les donnée
        swap(temp)
        return *this;
    } // temp est détruit ici, son destructeur est appelé, la mémoire de temp.tab 
      // (qui était à l'origine celle de l'objet courant) est libérée
    en ayant une implémentation de swap qui prendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void Plateau::swap(Plateau & other){
        // 2 - la hauteur de l'objet en cours devient celle de la copie
        std::swap(hauteur, other.hauteur);
        // 3 - la largeur de l'objet en cours devient celle de la copie
        std::swap(largeur, other.largeur);
        // 4 - on interverti l'adresse représentée par tab dans l'objet en cours
        std::swap(tab, other.tab):
    }
    (*) D'aucun estiment que, étant donné qu'il faut quand même créer une copie temporaire de l'objet passé en paramètre, il est tout aussi correct de passer directement l'objet qui sert de modèle à l'affectation sous la forme de valeur à l'opérateur d'affectation, sous une forme proche de (toutes modifications apportées)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Plateau& Plateau::operator=(Plateau copiePlateau) // la copie est créée directement ici
    {
       // on interverti les donnée
        swap(copiePlateau)
        return *this;
    } // copiePlateau est détruit ici, son destructeur est appelé, la mémoire de copiePlateau.tab 
      // (qui était à l'origine celle de l'objet courant) est libérée
    Il y a des arguments en faveur des deux optiques, mais le débat reste malgré tout ouvert

    Enfin, il faut avouer que le fait de jouer avec les pointeurs et l'allocation dynamique de la mémoire ne sert qu'à se faire inutilement du mal dans le cas présent.

    La bibliothèque standard de C++ vient, en effet, avec une classe qui s'occupe, justement, de gérer correctement les tableaux contigus d'éléments appelée vector, disponible dans l'espace de noms std (comme tout ce qui est fourni par le standard) par simple inclusion du fichir <vector>.

    Grâce à cette classe, tu n'as même plus besoin de te faire ch..er à respecter la forme canonique orthodoxe de coplien, simplement parce qu'elle fournit déjà tout ce qu'il faut pour permettre la copie et l'affectation correcte.

    Ta classe Plateau pourrait donc ressembler à 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
    class Plateau{
        public:
            Plateau ();
            Plateau (size_t h, size_t l);
            void affiche();
            void affiche_fichier();
            size_t getLargeur() const;
        private:
            size_t hauteur;
            size_t largeur;
            std::vector<Etat> tab;
    }
    dont les constructeurs seraient implémentés sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Plateau::Plateau():hauteur(21),largeur(51),tab(hauteur*largeur){}
    Plateau::Plateau(int h, int l):hauteur(h),largeur(l){
        /* est que cela a du sens ??? */
        if (!(hauteur % 2 != 0 && largeur % 2 != 0))
        {
            hauteur = 21;
            largeur = 51;
        }
        tab = std::vector<Etat(hauteur, largeur);
    }
    Ceci dit, si je peux comprendre l'intérêt qu'il y a à présenter la forme canonique de coplien et la règle des trois grands, je trouve particulièrement mauvais d'imposer son utilisation au lieu d'expliquer la manière de s'en passer en utilisant les classes, fournies par le langage, qui présentent un comportement RAIIsant .

    De plus, la forme canonique de Coplien ne s'applique qu'à des classes ayant sémantique de valeur. Or, une classe Plateau aura régulièrement une sémantique qui est plus proche de la sémantique d'entité. Et la forme canonique de Coplien n'a aucun sens pour ce genre de classes, vu que les classes ayant sémantique d'entité sont, typiquement, non affectable et non copiables.

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2013
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Bonjour

    Merci de m'avoir fait cette réponse aussi longue qu'intéressante. C'est bien de savoir que y a des gens qui peuvent prendre beaucoup de leur temps pour aider expliquer.

    Je devrais relire certainement plusieurs fois pour saisir toutes les astuces car je pense que tu viens de me refaire une partie de mon cours. Notre prof ne faisait que lire les ppt du cours fait par le full prof et ça aidait pas beaucoup. Donc tout je que je sais du C++ , je l'ai appris des tutos sur le net.

    1-Comme tu l'as un peu deviné , j'ai pas copier du code mais je suis basé sur ce que j'ai appris des tutos (erreur de débutant)
    2- Bien vu pour les unsigned int , j'y ai pas pensé.
    3- Pour les pointeurs , je suis leur ennemi numéro un. Déjà j'aimais pas en C. De tous les tutos que j'ai fait ça recommander de les éviter.
    On me l'impose dans l'énoncé du projet. Je peux même t'envoyer le pdf juste histoire de voir.
    4- Pour le constructeur de copie , tu m'as appris beaucoup de choses. Tout ce que je savais c'est quand on utilise des pointeurs , le compilateur en crée un mais qui n'est pas trop intelligent.

    Je vais prendre le temps de bien comprendre toutes tes explications et recommandations avant de les appliquer. Je mettrai "résolu" après... faut être sur hein

  6. #6
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2013
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Merci pour tout ce fut très instructif et ça éclaircit beaucoup.

    J'ai préféré me baser sur tes explications et modifications de mon code plutôt que tes propositions pour respecter au mieux l'énoncé de mon sujet.

    Ceci dit si ça dépendait que de moi j'aurais utilisé tes propositions. Comme tu le dis si bien , faut pas se compliquer la vis quand on peut se la simplifier.

    Bonne journée et à la prochaine

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 04/01/2013, 16h25
  2. Réponses: 7
    Dernier message: 27/05/2011, 17h58
  3. Tableau d'objets en parametres de constructeurs
    Par fefe69 dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 07/03/2009, 13h12
  4. Réponses: 15
    Dernier message: 23/06/2006, 13h57

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