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 :

La surcharge d'opérateurs


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 26
    Par défaut La surcharge d'opérateurs
    Bonjour à tous.

    Voila, donc j'ai un petit travail à effectuer ce week end, et jusqu'à maintenant je galère énormément, c'est pourquoi j'ai décidé de venir poster ici.

    Je dois, à partir d'une classe vecteur, surcharger beaucoup beaucoup d'opérateurs (= += ++ -- << >> == ....). Le problème c'est que je suis totalement débutant en C++ et que je n'ai jamais vu ce genre de surcharge ! Les cours reçus sont vraiment insuffisants puisqu'on a fait que parler des opérateurs, on a pas eu de réel exemple concret. En plus les infos sur internet ne correspondent pas totalement à mon problème (incrémenter un nombre, OK, mais incrémenter un vecteur...), du coup ça m'embrouille plus que tout le reste !

    Donc je voulais deja vous demander ce que vous pensiez de mes opérateurs que j'ai deja surchargés. Pour indication ma classe vecteur à une dimension est constituée d'une taille et d'un tableau pointant sur des entiers (rien que ça j'arrive pas trop à comprendre à quoi ça sert dans le cas de vecteurs à UNE dimension...). En effet, le prof voulait absolument qu'on crée un tableau et un taille en attributs, personnellement je n'ai pas du tout compris car moi j'aurais pas fait comme ça, du moins pas pour des vecteurs à une dimension...Le pauvre a essayé de me faire comprendre mais il a vite abandonné, ce qui me rend encore plus seul au monde ! Voici mon code :
    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
     
    // Acces aux elements
      int& vecteur::operator[](const int rang) {
        return tab[rang];
      }
     
    // affectation : =(vecteur), =(int)
      vecteur& vecteur::operator=(const vecteur& v) {
        vecteur tmp;
        tmp.taille = v.taille;
        tmp.tab = v.tab;
        return tmp;
      }
      vecteur& vecteur::operator=(const int nb) {
        vecteur tmp;
        tmp.taille = 1;
        tmp.tab[0] = nb;
        return tmp;
      }
     
    // incrementation/decr. : ++, ++(int), --
      vecteur& vecteur::operator++() {
        taille++;
        return (*this);
      }
     
      vecteur vecteur::operator++(const int i) {
        vecteur v = *this;
        taille++;
        return v;
      }
     
      vecteur& vecteur::operator--() {
        taille--;
        return (*this);
      }

    Ensuite, j'ai quelques petites questions justement sur ces opérateurs car le but n'est bien évidemment pas que vous me donniez la réponse sans explication, mais j'aimerais surtout comprendre afin de pouvoir le refaire moi même par la suite !
    1) L'opérateur d'affectation = : Dans mon cas, on peut dire qu'il retourne un nouvel objet ayant les valeurs voulues. Mais le truc c'est qu'il n'a changé en rien la valeur de l'objet courant this ??
    2) J'ai du mal à saisir la différence entre ++() et ++(int) malgrès ce que j'ai lu sur le net si ce n'est que l'un retourne la valeur incrémentée, l'autre non, mais alors à quoi ça sert ?
    3) Comment incrémenter/décrementer mes vecteurs, si ce n'est en changeant leur taille ?


    Merci de votre aide et bonne fin de week end ;-)

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 26
    Par défaut
    Je me permets le double post pour rajouter une question.

    Mes opérateurs d'affectation = ne seraient-ils pas plus justes en les écrivant comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
      vecteur& vecteur::operator=(const vecteur& v) {
        taille = v.taille;
        tab = v.tab;
        return (*this);
      }
      vecteur& vecteur::operator=(const int nb) {
        taille = 1;
        tab[0] = nb;
        return (*this);
      }
    En exécutant, j'obtient le bon résultat et ensuite j'ai un truc "glibc detected....backtrace :....memory map:..." qui s'affiche avec tout des adresses mémoires, qu'est-ce que c'est ?
    Voici mon main (ou plutôt celui fourni par mon prof) :
    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
    69
     
    #include <iostream>
     
     
     
    // Include de l'application
     
    #include "Vecteur.h"
     
     
    using namespace std;
     
     
    int main(int argc, char **argv)
     
    {
     
     
     
    	cout << "PROGRAMME DE TEST" << endl;
     
     
     
    	// Constructeurs
     
    	vecteur v1(3);
     
    	vecteur v2 = v1;
     
    	vecteur v3;
     
     
     
    	v1[0] = 2;
     
    	v1[1] = 4;
     
    	v1[2] = 6;
            v1++;
            v1[3] = 8;
     
     
    	cout << "v1 :	" << v1 << endl;
     
     
     
    	v2 = v1;
     
    	cout << "v2 = v1 :	" << v2 << endl;
     
     
     
    //	v2++;
     
    //	cout << "v2++ :	" << v2 << endl;
     
     
     
    //	v3 = v1 + v2;
     
    //	cout << "v3 = v1 + v2 :	" << v3 << endl;
     
     
     
     
     
    	cout << "SORTIE TEST" << endl;
     
    }

  3. #3
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    1) l'op= doit retourner une ref sur *this. Pas un temporaire (comme tu l'as dis ça n'aurait aucun sens).
    Renseigne toi sur l'idiome copy'n'swap pour implémenter l'op= sous la bonne forme.


    2) Faut d'abord comprendre l'utilisation avant de surcharger : il y'a deux opérateur ++ un postfixé et un préfixé. l'opérateur préfixé renvoie une référence sur *this, l'incrémentation est donc "de suite valable".
    L'opérateur postfixé quand à lui retourne par valeur une copie de *this, et qui n'a donc pas subit l'incrémentation. (en français dans le texte c'est pas facile à expliquer donc regarde ce bout de code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int main()
    {
        int i = 0;
     
        std::cout << i++ << std::endl; // on travaille sur une copie non incrémenté
        std::cout << ++i << std::endl; // on travaille sur *this donc l'incrémentation est directement 'valable'
     
        return 0;
    }
    Maintenant du côté surcharge : operator++() correspond à la version préfixé là où operator++(int) correspond à la version postfix. (pas de const int).

    Quand on sait que la version préfixé renvoie une référence on peut facilement déduire que les signatures seront :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    T& operator++(); //prefix
    T    operator++(int); //postfix
    Et voici le squellette de ces opérateur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    T& operator++()
    {
          //les opérations qui correspondent à l'incrémentation
          return *this;
    }
     
    T operator++(int)
    {
          T bu = *this;
          ++(*this); //on se sert de l'opérateur précédemment défini
          return bu; // on retourne une version non incrémenté d'où le comportement vu au dessus.
    }
    3) Amha ça n'a pas de sens incrémentée un vecteur...

    4) Il faut fournir une version const de l'opérateur []

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 26
    Par défaut
    Tout d'abord bonjour et merci d'avoir répondu !

    J'ai corrigé les opérateurs d'affectation et d'incrémentation / décrementation et je t'en remercie ;-)

    Concernant le point 3, je suis d'accord avec toi...selon moi incrémenter un vecteur dans le sens du proche voudrait probablement dire "Augmenter la taille du tableau" et c'est donc ce que j'ai fait.

    Concernant ton point 4, je ne comprends pas : mon operateur [] est deja défini avec un const ??

    Et sur mon double post, que penses tu de cette erreur à l'affichage ?

  5. #5
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Ouai au vue du main l'incrémentation veut dire incrémenter la taille. (définitivement ça n'a pas de sens).
    Pour la version const non je parle de quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    const int& operator[](int rang) const;
    int& operator[](int rang);
    Pour le problème d'affichage, à la suite de detected y'a un message c'est ça qu'est important. Ou alors montre le code entier. (probablement une segfault).

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 26
    Par défaut
    ok

    Le rendu de l'erreur est :
    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
     
    PROGRAMME DE TEST
    v1 :	4 : �O��(���*�
     
    v2 = v1 :	4 : �O��(���*�
     
    v1 == v2 ? true
    v2++ :	5 : 
     
    SORTIE TEST
    *** glibc detected *** ./tp: free(): invalid next size (fast): 0x0804c008 ***
    ======= Backtrace: =========
    /lib/tls/i686/cmov/libc.so.6[0xb7db3604]
    /lib/tls/i686/cmov/libc.so.6(cfree+0x96)[0xb7db55b6]
    /usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7f96231]
    /usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0xb7f9628d]
    ./tp[0x8048f02]
    ./tp[0x8048b47]
    /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7d5a775]
    ./tp[0x80487b1]
    ======= Memory map: ========
    08048000-0804a000 r-xp 00000000 08:06 1554644    /home/ben54120/utbm/cpp_tp1/tp
    0804a000-0804b000 r--p 00001000 08:06 1554644    /home/ben54120/utbm/cpp_tp1/tp
    0804b000-0804c000 rw-p 00002000 08:06 1554644    /home/ben54120/utbm/cpp_tp1/tp
    0804c000-0806d000 rw-p 0804c000 00:00 0          [heap]
    b7c00000-b7c21000 rw-p b7c00000 00:00 0 
    b7c21000-b7d00000 ---p b7c21000 00:00 0 
    b7d43000-b7d44000 rw-p b7d43000 00:00 0 
    b7d44000-b7ea0000 r-xp 00000000 08:06 1618872    /lib/tls/i686/cmov/libc-2.9.so
    b7ea0000-b7ea1000 ---p 0015c000 08:06 1618872    /lib/tls/i686/cmov/libc-2.9.so
    b7ea1000-b7ea3000 r--p 0015c000 08:06 1618872    /lib/tls/i686/cmov/libc-2.9.so
    b7ea3000-b7ea4000 rw-p 0015e000 08:06 1618872    /lib/tls/i686/cmov/libc-2.9.so
    b7ea4000-b7ea7000 rw-p b7ea4000 00:00 0 
    b7ea7000-b7eb4000 r-xp 00000000 08:06 1586300    /lib/libgcc_s.so.1
    b7eb4000-b7eb5000 r--p 0000c000 08:06 1586300    /lib/libgcc_s.so.1
    b7eb5000-b7eb6000 rw-p 0000d000 08:06 1586300    /lib/libgcc_s.so.1
    b7eb6000-b7eb7000 rw-p b7eb6000 00:00 0 
    b7eb7000-b7edb000 r-xp 00000000 08:06 1618883    /lib/tls/i686/cmov/libm-2.9.so
    b7edb000-b7edc000 r--p 00023000 08:06 1618883    /lib/tls/i686/cmov/libm-2.9.so
    b7edc000-b7edd000 rw-p 00024000 08:06 1618883    /lib/tls/i686/cmov/libm-2.9.so
    b7edd000-b7fc1000 r-xp 00000000 08:06 245601     /usr/lib/libstdc++.so.6.0.10
    b7fc1000-b7fc5000 r--p 000e3000 08:06 245601     /usr/lib/libstdc++.so.6.0.10
    b7fc5000-b7fc6000 rw-p 000e7000 08:06 245601     /usr/lib/libstdc++.so.6.0.10
    b7fc6000-b7fcc000 rw-p b7fc6000 00:00 0 
    b7fde000-b7fe1000 rw-p b7fde000 00:00 0 
    b7fe1000-b7fe2000 r-xp b7fe1000 00:00 0          [vdso]
    b7fe2000-b7ffe000 r-xp 00000000 08:06 1586147    /lib/ld-2.9.so
    b7ffe000-b7fff000 r--p 0001b000 08:06 1586147    /lib/ld-2.9.so
    b7fff000-b8000000 rw-p 0001c000 08:06 1586147    /lib/ld-2.9.so
    bf95c000-bf971000 rw-p bffeb000 00:00 0          [stack]
    Abandon

  7. #7
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Faut vraiment que tu nous donne le code complet avec. ! (on sait même pas par quelle moyen tu stockes les données de ton vecteur )

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par ben54120 Voir le message
    (rien que ça j'arrive pas trop à comprendre à quoi ça sert dans le cas de vecteurs à UNE dimension...). En effet, le prof voulait absolument qu'on crée un tableau et un taille en attributs, personnellement je n'ai pas du tout compris car moi j'aurais pas fait comme ça, du moins pas pour des vecteurs à une dimension...
    C'est pourtant simple: Si tu ne mémorises pas la taille, tu n'auras aucun moyen de la connaître! Et donc, de vérifier qu'il n'y a pas de débordement...
    Au passage, tout ton code présente un énorme défaut: La taille doit, au début et à la fin de toute fonction, refléter exactement celle du buffer alloué! Donc, tu n'as pas le droit de changer la variable membre taille sans réallouer le buffer.

    Quant à l'incrémentation, cela dépend si on parle du vecteur ou de son contenu. Imagine une addition de vecteurs, ça peut être:
    soit la concaténation des deux vecteurs, bout-à-bout.
    soit un vecteur contenant les sommes des valeurs des deux vecteurs en entrée (on peut exiger qu'ils aient la même taille).
    Pour l'incrémentation, c'est la même chose: On peut soit incrémenter sa taille, soit incrémenter chacune de ses valeurs.
    Il en va de même pour les comparaisons.

    1. L'opérateur d'affectation ne retourne pas un nouvel objet, il modifie l'objet courant et retourne une référence vers lui.
    2. L'opérateur de pré-incrémentation peut retourner directement une référence sur l'objet, et n'a pas besoin d'en faire la moindre copie. L'opérateur de post-incrémentation est obligé de faire une copie de l'objet avant de l'incrémenter, et retourner cette copie par valeur.
      Par extension, un type non-copiable ne peut pas avoir de vrai opérateur de post-incrémentation.
    3. Voir plus haut.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 26
    Par défaut
    ok, mais alors à quoi sert ce fameux tableau en attributs ?
    C'est ça qui me bloque !

    Et pour faire le produit scalaire, du coup je vois vraiment pas comment faire vu que je ne sais pas ce que représente ce tableau...des points ? des vecteurs ? aucune idée

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    J'ai l'impression que tu confonds le terme vecteur tel qu'il est employé en géométrie ("des coordonnées dans un plan/espace/hyperplan/etc.") et tel qu'il est employé en informatique ("une liste de valeurs, de longueur arbitraire et non fixe").

    Il existe peut-être un lien logique entre ces deux termes, une grande théorie unificatrice, mais je ne la connais pas: Je me suis limité à la géométrie dans l'espace, où les vecteurs n'avaient au plus que trois valeurs (pour les trois dimensions).
    J'ignore s'il est seulement possible de faire le produit scalaire de deux vecteurs "liste"...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    J'ignore s'il est seulement possible de faire le produit scalaire de deux vecteurs "liste"...
    Sans aucun problème, du moins dans un espace préhilbertien (K-espace vectoriel muni, justement, d'un produit scalaire).
    Cf. cette page si tu veux les formules du produit scalaire "général".
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    C'est un peu technique pour moi, mais d'après ce que j'ai cru comprendre, ils doivent à ce moment-là avoir le même nombre de valeurs, non?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. [C#] Tri d'objet et surcharge d'opérateur
    Par Royd938 dans le forum Windows Forms
    Réponses: 6
    Dernier message: 17/12/2007, 00h26
  2. Petit probléme de surcharge d'opérateur .
    Par Clad3 dans le forum C++
    Réponses: 20
    Dernier message: 11/04/2005, 20h15
  3. Problème de surcharge d'opérateurs
    Par Hell dans le forum C++
    Réponses: 17
    Dernier message: 17/01/2005, 16h01
  4. Cumul de surcharges d'opérateurs
    Par Nats dans le forum C++
    Réponses: 2
    Dernier message: 11/10/2004, 13h37
  5. [VB .NET] Surcharge d'opérateur
    Par Franckintosh dans le forum VB.NET
    Réponses: 2
    Dernier message: 07/09/2004, 19h05

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