IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

surcharge opérateur ()


Sujet :

Langage C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2015
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 2
    Points : 2
    Points
    2
    Par défaut surcharge opérateur ()
    Bonjour,

    Je développe une classe Matrice, et après avoir cherché sur internet, je suis parvenu à avoir une classe qui marche bien. Néanmoins, dans un des exemples, j'ai noté que l'opérateur () était surchargé 2 fois, et j'aimerai comprendre pourquoi.

    Voici la partie de 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
     
    template<typename T> 
    class Matrix
    {
    public:
     
        T&  operator()(size_t r, size_t c) 		  { return(tableau[c + r*col]);  } 
        T   operator()(size_t r, size_t c)  const   {  return(tableau[c + r*col]);  } 
     
    .....
     
    private :
        size_t      row;   // nombre de lignes
        size_t      col;   // nombre de colonnes
        vector<T> 	tableau;
     
    };

    je vois bien la première surcharge. Mais la seconde ? et dans quel contexte ?

    Merci bien

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 190
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 190
    Points : 17 146
    Points
    17 146
    Par défaut
    il y a une surcharge non constante, et une autre constante.

    La premiere permet de prendre une référence (modifiante) sur un élément d'une matrice modifiable.
    La seconde permet de prendre une copie d'un élément d'une matrice constante.

    Exactement comme begin() ou end() ont deux surcharges dans std::vector.


    Cela dit, le changement de taille d'une matrice n'a pas de sens concret. Tu devrais prendre la taille en parametre de template, et utiliser std::array<T, taille*taille> comme conteneur de cases.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Janvier 2003
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Janvier 2003
    Messages : 4
    Points : 10
    Points
    10
    Par défaut
    Les deux te permettent d'acceder a tes données.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    T&  operator()(size_t r, size_t c)
    Cette methode (1) te donne acces en mode lecture ecriture.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    T   operator()(size_t r, size_t c)  const
    Cette methode (2) te retourne une copie et tu en faire ce que tu veux.

    Une suggestion est de l'écrire comme ça, l'implementation ne change pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const T&   operator()(size_t r, size_t c)  const
    Ton compilateur choisira la methode appropriée.
    Un example:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Matrix<std::string> stringMatrix;
     
    const std::size_t sz = stringMatrix(1, 2).size(); // methode (2) est utilisée.
    stringMatrix(1, 2).clear(); // methode (1) est utilisée.

  4. #4
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par Jerome2568 Voir le message
    Ton compilateur choisira la methode appropriée.
    Un example:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Matrix<std::string> stringMatrix;
     
    const std::size_t sz = stringMatrix(1, 2).size(); // methode (2) est utilisée.
    stringMatrix(1, 2).clear(); // methode (1) est utilisée.
    En l'occurrence la méthode non const sera appelée les deux fois, puisque l'objet stringMatrix n'est pas const.
    Un meilleur exemple serait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::matrix<int> addMatrix(const Matrix<int>& a, const Matrix<int>& b); // garantit que a et b ne seront pas modifiées -> uniquement les méthodes const peuvent être utilisées
    Il y a un autre intérêt à marquer une méthode const: si la méthode const modifie un des membres de l'objet, le compilateur générera une erreur (à mois que le membre en question ait été déclaré mutable).

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

    Informations professionnelles :
    Activité : aucun

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

    Pour faire simple : lorsque -- pour une raison quelconque -- on a déterminé que la matrice (parce que c'est ce dont on parle ici, mais nous pourrions parler de n'importe quel autre type de donnée) ne peut pas être modifié en précisant que c'était un "élément constant", le compilateur refusera systématiquement toute tentative d'appel à une fonction qui pourrait éventuellement risquer de modifier la donnée en question

    Pour les fonctions libres, cela signifie que nous ne pourrons appeler que des fonctions qui reçoivent la donnée en question par valeur (parce que cela occasionne une copie et si modification il y a au niveau de la fonction appelée, elle a lieu sur... la copie et non sur la donnée d'origine) ou par référence constante (parce que le passage par référence n'occasionne pas de copie, mais le fait qu'on prévienne le compilateur que c'est un élément qui n'est pas susceptible d'être modifié lui suffit pour dire qu'il ne le sera pas)

    Pour les fonctions membres de la classe, cela passe par le fait d'indiquer explicitement au compilateur que la fonction ne modifiera pas l'objet au départ duquel elle est appelée. Et cela se fait en ... ajoutant le mot clé const après la liste des paramètres.

    De cette manière, le compilateur pourra "traquer" tous les cas où tu pourrais éventuellement en arriver à modifier une donnée dont tu as dit qu'elle ne pouvait pas l'être. Et, crois moi, il sera beaucoup plus buté que toi et beaucoup plus précis pour trouver les cas qui posent problème

    Ainsi, la version const T& operator()(size_t r, size_t c) const de ton opérateur dit (plus ou moins textuellement) que "cet opérateur renvoi une référence qui ne pourra pas être modifiée" (ca, c'est le const T&) et que cet opérateur s'engage à ne pas modifier la donnée au départ de laquelle il a été appelé (ca, c'est le deuxième const). Si, au lieu de renvoyer un T const &, nous venions à renvoyer un simple T & (tu remarqueras l'absence du mot clé const ), le compilateur nous engueulerait sous une forme qui pourrait ressembler à
    espèce d'imbécile!!! tu me dit que l'opérateur ne peut pas modifier l'objet courant, mais le fait que tu renvoie une référence constante permettrait à la fonction appelant cet opérateur de le faire... tu crois pas qu'il y a un malaise quelque part ?
    (oui, je sais, j'anthropomorphise très fort )

    Dés lors, on peut exprimer les choses sous cette forme : lorsque l'on a affaire à une donnée définie comme constante, on ne peut appeler que des fonctions libres qui recoivent cette donnée sous forme de valeur ou sous forme de référence constante et on ne peut appeler que les fonctions membres qui se sont explicitement engagées à ne pas la modifier.

    Par contre, quand on a affaire à une donnée qui n'est pas définie comme constante, on peut faire appel à n'importe quelle fonction : les fonctions membres qui se sont engagées à ne pas la modifier comme n'importe quelle autre.

    Ce principe est connu sous le terme de const-correctness et est particulièrement intéressant à garder à l'esprit (toute fonction ne devant pas modifier une donnée devrait manipulée cette donnée sous une forme constante), car cela te permettra souvent d'éviter bien des heures de débugage et d'arrachage de cheveux à te demander "mais où et pourquoi cette @#@@@ de donnée a été modifiée???"
    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

Discussions similaires

  1. Portabilitée : Surcharge opérateur de comparaison
    Par Dimitri_87 dans le forum C++
    Réponses: 11
    Dernier message: 15/12/2006, 16h14
  2. Surcharge opérateur +
    Par nunurs83 dans le forum C++
    Réponses: 6
    Dernier message: 31/10/2006, 09h48
  3. [Débutant]Surcharge opérateur +
    Par Geolem dans le forum Débuter
    Réponses: 13
    Dernier message: 05/12/2005, 10h16
  4. surcharge opérateur << et >>
    Par Azharis dans le forum Débuter
    Réponses: 11
    Dernier message: 02/11/2005, 21h22
  5. Surcharge opérateurs
    Par ghostdogpr dans le forum C++
    Réponses: 5
    Dernier message: 18/03/2005, 11h51

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