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 :

declaration opérateurs avec l'objet courant


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2016
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2016
    Messages : 24
    Points : 16
    Points
    16
    Par défaut declaration opérateurs avec l'objet courant
    Bonjour ,
    le suis débutant en programmation C++ et j'ai du mal à déclarer les opérateurs < et <= en utilisant :*this (l'objet courant).
    Est ce que quelqu'un peut m'aider sur ça.
    Merci d'avance .

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Il suffit de consulter la section sur la surcharge des opérateurs de la .

    En particulier cette entrée : http://cpp.developpez.com/faq/cpp/?p...l-operateur-lt

  3. #3
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Je suggère d'écrire une fonction friend compare qui centralise la logique de comparaison de la classe/structure.
    La surcharge des opérateurs souhaités est ensuite aisée.
    Voici un exemple assez général:
    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
    class MyClass
    {
    	std::string one;
    	int two;
    	//bazar_truc three;
    public:
    	friend intptr_t compare(MyClass const & l, MyClass const & r)
    	{
    		intptr_t cmp = l.one.compare(r.one);
    		if (cmp == 0)
    		{
    			cmp = (l.two - r.two);
    			//if (cmp == 0)
    			//	cmp = compare(l.three, r.three);
    			//		etc...
    		}
    		return cmp;
    	}
    };
     
    inline bool operator<(MyClass const & l, MyClass const & r)
    {
    	return compare(l, r) < 0;
    }
     
    inline bool operator==(MyClass const & l, MyClass const & r)
    {
    	return compare(l, r) == 0;
    }
     
    inline bool operator>=(MyClass const & l, MyClass const & r)
    {
    	return compare(l, r) >= 0;
    }
    Maintenant, si pour une raison ou une autre on tient absolument à utiliser en cascade les opérateurs déjà surchargés des sous-objets, une solution ressemblerait à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class MyClass
    {
    	std::string one;
    	int two;
    	//bazar_truc three;
    public:
    	bool operator<(MyClass const & v) const
    	{
    		return (this->one < v.one
    			|| (!(v.one < this->one) && (this->two < v.two
    				/*|| (!(v.two < this->two) && this->three < v.three)*/)));
    	}
    };
    Mais je trouve cette autre approche fastidieuse et sujette à erreur s'il faut écrire plusieurs operateurs.

  4. #4
    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
    Il existe une astuce, dont j'ai plus le nom si tenté qu'il y en ait un, pour n'avoir à écrire que 2 opérateurs et que tous les autres se déduisent à partir de ces deux-là : == et <
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    bool operator==(const T& l, const T& r) { return ...; }
    bool operator<((const T& l, const T& r) { return ...; }
    bool operator!=(const T& l, const T& r) { return !(l == r); }
    bool operator<=(const T& l, const T& r) { return (l == r) || (l < r); }
    bool operator>(const T& l, const T& r) { return !(l == r) && !(l < r); }
    bool operator>=(const T& l, const T& r) { return (l == r) || !(l < r); }
    En théorie il est même possible de n'utiliser que operator< avec bool operator==(const T& l, const T& r) { return !(l < r) && !(r < l); } mais avoir l'implémentation de == peut accélérer les choses selon la complexité de l'opérateur <.
    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.

  5. #5
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    C'est même plus simple que ça encore
    Voici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    bool operator==(const T& l, const T& r) { return ...; }
    bool operator<(const T& l, const T& r) { return ...; }
    bool operator!=(const T& l, const T& r) { return !(l == r); }
    bool operator<=(const T& l, const T& r) { return !(r < l); }
    bool operator>(const T& l, const T& r) { return (r < l); }
    bool operator>=(const T& l, const T& r) { return !(l < r); }

  6. #6
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2016
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2016
    Messages : 24
    Points : 16
    Points
    16
    Par défaut
    Citation Envoyé par camboui Voir le message
    Je suggère d'écrire une fonction friend compare qui centralise la logique de comparaison de la classe/structure.

    Maintenant, si pour une raison ou une autre on tient absolument à utiliser en cascade les opérateurs déjà surchargés des sous-objets, une solution ressemblerait à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class MyClass
    {
    	std::string one;
    	int two;
    	//bazar_truc three;
    public:
    	bool operator<(MyClass const & v) const
    	{
    		return (this->one < v.one
    			|| (!(v.one < this->one) && (this->two < v.two
    				/*|| (!(v.two < this->two) && this->three < v.three)*/)));
    	}
    };
    Mais je trouve cette autre approche fastidieuse et sujette à erreur s'il faut écrire plusieurs operateurs.

    Merci pour vos réponses.
    Je vais utiliser la solution ci-dessus car je dois utiliser *this (l'objet courant). Mais dans mon cas j'ai une classe temps donc je dois comparer heures,minutes et secondes.
    Sinon j'ai pas compris ce morceau de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    return (this->one < v.one
    			|| (!(v.one < this->one) && (this->two < v.two
    				/*|| (!(v.two < this->two) && this->three < v.three)*/)));

    c'est quoi le one ,two , three ...est ce que je dois mettre à leurs places heure minute et seconde ?

  7. #7
    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
    @Camboui> dans l'absolu oui, mais il faut prendre en compte la complexité de l'opérateur== face à l'opérateur<, découper en utilisant == autant que possible peut être bénéfique performencement parlant

    je dois utiliser *this
    C'est vriament l'énoncé ? Et personne ne lui a fait remarquer que ça ne veut rien dire ?
    Il veut quoi ? Voir juste un *this apparaître dans le code ?
    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.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2016
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2016
    Messages : 24
    Points : 16
    Points
    16
    Par défaut
    Citation Envoyé par Bousk Voir le message
    @Camboui> dans l'absolu oui, mais il faut prendre en compte la complexité de l'opérateur== face à l'opérateur<, découper en utilisant == autant que possible peut être bénéfique performencement parlant
    tu veux dire que je doit déclarer aussi l'opérateur ==?


    Citation Envoyé par Bousk Voir le message
    C'est vriament l'énoncé ? Et personne ne lui a fait remarquer que ça ne veut rien dire ?
    Il veut quoi ? Voir juste un *this apparaître dans le code ?
    exactement l'utilisation de l'objet local this est obligatoire je ne vois pas pourquoi mais c'est bien le cas.

  9. #9
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    @Bousk, le but de ma réponse était de donner plus de visibilité à ta proposition .

    A propos de performance, je pense qu'elle a lieu à trois moments distincts, tous importants:
    -le temps dévolu au développement,
    -la vitesse d'exécution du code,
    -le temps dévolu à la maintenance.

    L'idéal étant de réunir les trois
    L'approche que j'ai proposé en passant par une fonction compare réunit les trois me semble-t-il.

    Mais notre ami @CANADG veut une solution "académique" pour son operator<, voici une des meilleures je crois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    return
     ((((this->heure * 64) + this->minute) * 64) + this->seconde)
     <
     ((((v.heure * 64) + v.minute) * 64) + v.seconde);
    Simple, lisible et performante. Et elle utilise this

    Et oui, j'ai bien multiplié par 64 et non 60, c'est exprès. Et il n'y a aucun branchement conditionnel, c'est aussi exprès.

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

    Informations professionnelles :
    Activité : aucun

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

    De manière générale, il y a deux possibilités :
    Soit on compare l'objet courant à "un autre", sous une forme qui serait proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class MaClasse{
    public:
        /* ... */
        bool operator ==(MaClasse const &) const;
        bool operator <(MaClasse const &) const;
        bool operator >(MaClasse const &) const;
        bool operator <=(MaClasse const &) const;
        bool operator >=(MaClasse const &) const;
    private:
        /* ... */
    };
    soit on utilise des fonctions libres pour la comparaison, sous 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
    class MaClasse{
    public:
        /* ... */
    private:
        /* ... */
    };
     
        bool operator ==(MaClasse const &, MaClasse const &) const;
        bool operator <(MaClasse const &, MaClasse const &) const;
        bool operator >(MaClasse const &, MaClasse const &) const;
        bool operator <=(MaClasse const &, MaClasse const &) const;
        bool operator >=(MaClasse const &, MaClasse const &) const;
    Dans le premier cas, comme il s'agit de fonctions membres, les opérateurs ont forcément accès à l'ensemble des membres de la classe, et this est implicite, si bien qu'une code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool MaClasse::operator == (MaClasse const & other) const{
        return membre1 == other.membre1 && 
                  membre2 == other.membre2;
    }
    est tout à fait similaire au code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool MaClasse::operator == (MaClasse const & other) const{
        return this->membre1 == other.membre1 && 
                  this->membre2 == other.membre2;
    }
    Par contre, si on n'envisage de fournir que des fonctions libres, il n'y a pas d'objet courant (vu qu'il y a... l'objet qui correspond à l'opérande de gauche et celui qui correspond à l'opérande de droite), et il peut être intéressant de déclarer au minimum l'opérateur < et (éventuellement) l'opérateur == comme étant ami(s) de la classe.

    Maintenant, il est aussi possible de combiner les deux et d'avoir les opérateurs sous forme de fonction membre ET sous forme de fonction libre.

    Dans ce cas, l'implémentation des opérateurs sous forme de fonction membre feront sans doute (au moins pour < et == ) appel aux membres de la classe, et les version sous forme de fonction libre feront appel à la version sous forme de fonction membre, sous une forme qui serait au final proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MaClasse{
    public:
        /* je ne met que celui- là pour l'exemple*/
        bool operator ==(MaClasse const &) const;
    };
    bool MaClasse::operator == (MaClasse const & other) const{
        return this->membre1 == other.membre1 && 
                  this->membre2 == other.membre2;
    }
    bool operator(MaClasse const & c1, MaClasse const & c2){
        return c1.operator==(c2);
    }
    Il faut enfin savoir que les opérateurs prenant la forme de fonctions libres présentent de sérieux avantages, entre autres en termes de symétrie (par exempe : s'il existe une conversion possible entre un type quelconque et notre classe).

    En effet, si on considère qu'il est possible de convertir implicitement un int en un objet du type MaClasse, un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main(){
        MaClasse c;
        if(c == 10) { // conversion implicite de 10 en un objet de type MaClasse
            /* ... */
        }
    }
    sera toujours autorisé, mais un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main(){
        MaClasse c;
        if(10 == c) { // conversion implicite de 10 en un objet de type MaClasse
            /* ... */
        }
    }
    ne sera autorisé que si l'opérateur existe sous la forme d'une fonction libre (et, bien sur, il en va de même pour tous les opérateurs de comparaison, ainsi que pour les opérateurs mathématiques, d'ailleurs)
    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

  11. #11
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 469
    Points : 6 102
    Points
    6 102
    Par défaut
    Citation Envoyé par camboui Voir le message
    Je suggère d'écrire une fonction friend compare qui centralise la logique de comparaison de la classe/structure.
    La surcharge des opérateurs souhaités est ensuite aisée.
    Voici un exemple assez général:
    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 MyClass
    {
    	std::string one;
    	int two;
    	//bazar_truc three;
    public:
    	friend intptr_t compare(MyClass const & l, MyClass const & r)
    	{
    		intptr_t cmp = l.one.compare(r.one);
    		if (cmp == 0)
    		{
    			cmp = (l.two - r.two);
    			//if (cmp == 0)
    			//	cmp = compare(l.three, r.three);
    			//		etc...
    		}
    		return cmp;
    	}
    };
    J'aime bien l'idée.
    Cependant, dans ton exemple, à la place de intptr_t, j'aurais mis intmax_t au cas où on ait sizeof(int) > sizeof(intptr_t).

  12. #12
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    La comparaison multi-membres peut également être fait à travers std::tie.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    namespace detail {
      auto as_tuple(const T& o) { return std::tie(o.member1, o.member2);  }
    }
    bool operator==(const T& l, const T& r) { return detail::as_tuple(l) == detail::as_tuple(r); }
    bool operator<(const T& l, const T& r) { return detail::as_tuple(l) < detail::as_tuple(r); }

Discussions similaires

  1. [BO 5.1.8] Objet avec la date courante
    Par ninou58 dans le forum Designer
    Réponses: 15
    Dernier message: 09/06/2008, 08h48
  2. Objet Courant This et appel à un opérateur
    Par TheOyoStyledMan dans le forum C++
    Réponses: 2
    Dernier message: 13/06/2006, 16h35
  3. [FLASH MX] Problème avec l'objet Date
    Par n_tony dans le forum Flash
    Réponses: 13
    Dernier message: 22/03/2005, 13h44
  4. inclinaison d'un texte avec l'objet ID3DXFont
    Par tibyann dans le forum DirectX
    Réponses: 8
    Dernier message: 21/06/2004, 16h00
  5. Animations avec différents objet
    Par Mathieu.J dans le forum OpenGL
    Réponses: 6
    Dernier message: 09/06/2004, 14h18

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