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 :

objet en paramètre


Sujet :

C++

  1. #1
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 63
    Par défaut objet en paramètre
    Salut tous,

    J'essaye de créer une classe simple avec comme attribut un objet d'une autre classe, mon problème est le constructeur :

    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    class uneDate
    {
        private :
        int sonJour, sonMois, sonAnnee;
     
        public:
        uneDate(int,int,int);
        uneDate(const uneDate &);
        void afficheToi();
        void setDate(int, int, int);
        int getJour();
        int getMois();
        int getAnnee();
    };
     
    uneDate :: uneDate(int j, int m, int a)
    {
        sonJour = j;
        sonMois = m;
        sonAnnee = a;
    }
     
    uneDate :: uneDate(const uneDate & D)
    {
        sonJour = D.sonJour;
        sonMois = D.sonMois;
        sonAnnee = D.sonAnnee;
    }
     
    void uneDate :: afficheToi()
    {
        cout<<sonJour<<"/"<<sonMois<<"/"<<sonAnnee<<endl;
    }
     
    void uneDate :: setDate(int j, int m, int a)
    {
        sonJour = j;
        sonMois = m;
        sonAnnee = a;
    }
     
    int uneDate :: getJour(){return sonJour;}
    int uneDate :: getMois(){return sonMois;}
    int uneDate :: getAnnee(){return sonAnnee;}
     
    class unEvenement
    {
        private :
        uneDate saDate;
        char * intitule;
     
        public:
        unEvenement(uneDate , char * intitule);
        void afficheToi();
    };
     
    unEvenement :: unEvenement(uneDate  D, char * intit)
    {
        saDate.setDate(D.getJour(), D.getMois(), D.getAnnee());
        strcpy(intitule, intit);
    }
     
    void unEvenement :: afficheToi()
    {
        saDate.afficheToi();
        cout<<intitule<<endl;
    }
    Donc pour construire un objet unEvenement, il faut bien transmettre par valeur uneDate D, pour cela j'ai prévu un constructeur par recopie...Vainement semble-t-il, le compilateur me renvoie une erreur :
    no matching function for call to 'uneDate :: uneDate()'
    Un constructeur par défaut, qu'est-ce qu'il va en faire ? Franchement... Mon compilateur est-il drogué ?

  2. #2
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 23
    Par défaut
    Dans le constructeur de unEvenement, que fait tu de saDate ? Rien. Donc il est initialisé sans argument.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unEvenement :: unEvenement(uneDate  D, char * intit): saDate(D)
    {
        strcpy(intitule, intit);
    }
    Fonctionnera mieux.

    Je ne sais pas si c'est un devoir ou si tu es en train d'apprendre le C++ par toi même, dans tout les cas, t'apprendra plus vite, plus de choses en lisant un bon livre que ton bout de code fait très C là… avec le mot clef class en plus.

  3. #3
    Membre expérimenté
    Homme Profil pro
    Consultant BigData
    Inscrit en
    Juillet 2009
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Consultant BigData

    Informations forums :
    Inscription : Juillet 2009
    Messages : 129
    Par défaut
    Pour ton problème, je vois plusieurs solutions :
    1. Passer une référence à ton constructeur d'événement. Ainsi, tu es sur d'avoir le même élément en dehors et dans ton événement en ce qui concerne la date
    2. Passer directement l'objet de type uneDate au constructeur. Là, je ne vois pas en quoi il y aurait un problème. Tu peux très bien faire celà. Cependant, si tu modifie l'objet dans ton événement, l'objet fourni au constructeur ne sera pas modifié

    Peut-on voir le bout de code que tu utilises pour tester ceci ? il me semble qu'il manque une partie pour que l'on comprenne comment tu appelles les différentes méthodes ici présentes

    Autre point qui ne concerne pas ton problème mais qui simplifiera la relecture de ton code. Le nom de tes classes ne reflète pas ce qu'elles sont.
    Quand je regarde ta classe uneDate, elle a un jour, un mois et une année. La classe devrait donc s'appeler "Date" uniquement. Et une instance de date pourrait être appelée "uneDate".
    De la même manière, les attributs n'ont pas besoin de préciser leur appartenance à la classe dans leur nom, c'est implicite du fait que ce sont des attributs. Ainsi, tu peux écrire "jour" au lieur de "sonJour" par exemple.

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

    Informations professionnelles :
    Activité : aucun

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

    Pour commencer, j'aurais quelques remarques à faire sur ta classe uneDate:

    Tu devrais utiliser les listes d'initialisation dans tes constructeurs. Dans le cas présent, tu n'auras pas beaucoup d'avantages, mais, de manière générale, cela te permet d'initilaliser directement les membres de ta classe avec les bonnes valeurs plutôt que de passer par une double procédure d'initialisation à des valeurs par défaut suivie d'une affectation (et donc d'une copie) des membres.

    Les constructeurs prendraient donc des formes proches de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    uneDate::uneDate(int j, int m, int a) : sonJour (j),
                                            sonMois(m),
                                            sonAnnee(a){}
    uneDate::uneDate(uneDate const & other):sonJour (other.sonJour ), 
                                   sonMois(other.sonMois),
                                   sonAnnee(other.sonAnnee){}
    Ensuite, il faut savoir qu'il existe quatre fonctions qui seront systématiquement créée par le compilateur si tu ne les déclare pas toi-même:
    1. Le constructeur par défaut (qui ne sera pas créé par le compilateur si tu as ne serait-ce qu'un constructeur)
    2. le constructeur par copie
    3. le destructeur
    4. l'opérateur d'affectation
    Tant que tu ne travailles pas avec des pointeurs, tu peux te dire que le comportement standard de ces différentes fonctions sera amplement suffisant.

    Ainsi, le comportement standard du constructeur par copie sera de... copier les membres de ta classe "membre à membre". Il est donc tout à fait inutile de refaire toi-même ce que le compilateur fera tout aussi bien lui-même

    En outre, on peut estimer que ta classe uneDate a typiquement une sémantique de valeur: si tu modifie une de ses caractéristique, tu obtiens littéralement une autre date.

    Il ne me semble donc pas vraiment opportun de prévoir le mutateur (void setDate(int, int, int) ), surtout sous cette forme (si tu avais prévu setJour, setMois et setAnnee, on aurait pu discuter )

    Enfin, il y a un principe qu'il me semble important de rappeler: la loi demeter.

    Ce principe, si une classe A (ici : unEvenement) utilise (en interne) un objet de la classe B (ici : uneDate), conseille de faire en sorte que l'utilisateur de la classe A n'ait même pas conscience du fait d'utiliser la classe B.

    Ta classe unEvenement pourrait donc parfaitement 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 UnEvenement
    {
        private:
            UneDate date_;
            /* autres détails d'implémentation */
        public:
            UnEvenement(int j, int m, int a /* autres paramètres */):date_(j,m,a) /* ...*/{}
            /* si, vraiment, on a besoin de disposer de la date 
             * "depuis l'extérieur"
             */
            int getJour() const{return date_.getJour();}
            int getMois() const{return date_.getMois();}
            int getAnnee() const{return date_.getAnnee();}
    };
    De cette manière, si tu décide un jour de changer la manière dont la date est stockée dans ta classe événement, tu pourra le faire sans que le code qui utilise ta classe événement ne doive-être modifié d'aucune manière

    Enfin, il faut savoir que C++ fournit une classe spécialement prévue pour gérer les chaines de caractères: la classe std::string. Tu aurais vraiment intérêt à préférer l'utilisation de cette classe à celle des chaine "C style", car elle est beaucoup plus sécurisante et simple à utiliser
    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
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 63
    Par défaut
    Wow ! Merci tous pour vos réponses, c'est vraiment énorme !

    Bon voilà :
    Oussapik, voilà mon programme test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        uneDate date(1,1,2009);
        char * chaine = "voila";
        unEvenement E(d,chaine);
        E.afficheToi();
    (sinon tant que j'y suis, t'as raison koala01, le compilateur me renvoie une erreur de cast (conversion), ça marche parfaitement avec String, je voulais juste faire ça pour l'exercice, question de voir quels éventuels problèmes j'aurais...)

    Aux quatre éléments créés automatiquement par une classe, == est à rajouter, non ?

    Les setters sont bons, mais vraiment consommateurs de temps d'exécution...

    Je retiendrais cette loi de Demeter !

    Encore, merci tous !

  6. #6
    Invité
    Invité(e)
    Par défaut
    Non, l'operateur d'égalité n'est jamais défini par défaut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class Test {};
     
    //...
    Test t1, t2;
    t1 == t2; // ko
    Aussi, fais attention lorsque tu utilise des chaines litterales (c'est à dire écrite en dure dans ton programme) : elles sont de type char const* et non char*

  7. #7
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 63
    Par défaut
    Citation Envoyé par Joe Dralliam Voir le message
    Non, l'operateur d'égalité n'est jamais défini par défaut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class Test {};
     
    //...
    Test t1, t2;
    t1 == t2; // ko
    Aussi, fais attention lorsque tu utilise des chaines litterales (c'est à dire écrite en dure dans ton programme) : elles sont de type char const* et non char*
    t1==t2 ; n'a pas de sens, mais par exemple if(t1==t2) peut être évaluée, non ? Bref faudrait que je fasse un petit programme de test ! Merci en tout cas !

  8. #8
    Invité
    Invité(e)
    Par défaut
    Bah si t1==t2 peut être évalué alors if(t1==t2) peut aussi l'être... à condition que l'operateur respecte sa sémantique originale !

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par bounadalvidal Voir le message
    Aux quatre éléments créés automatiquement par une classe, == est à rajouter, non ?
    Pas forcément...

    l'opérateur == (tout comme l'opérateur < ) ne sont nécessaires que si tu souhaite pouvoir trier tes objets ou les retrouver.
    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

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

Discussions similaires

  1. [WD10]Passage d'objet en paramètres de methode
    Par Isildur dans le forum WinDev
    Réponses: 25
    Dernier message: 26/03/2007, 17h35
  2. Réponses: 2
    Dernier message: 28/09/2006, 20h04
  3. Réponses: 3
    Dernier message: 22/05/2006, 09h58
  4. [POO] débutant passer un objet en paramètre
    Par samplaid dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 02/05/2006, 12h46
  5. [DLL] Passage d'objet en paramètre
    Par TitiFr dans le forum Langage
    Réponses: 4
    Dernier message: 20/08/2005, 23h18

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