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 :

priorité des opérateurs surchargés


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut priorité des opérateurs surchargés
    Salut,

    Je suis en train de coder une petite classe de vecteurs (l'objet mathématique). Je code notamment les opérations produit scalaire, produit vectoriel etc...

    J'ai ajouté des opérateurs amis ostream pour afficher mes vecteurs facilement à l'écran.

    Imaginons que v1 et v2 soient deux vecteurs à 3 composantes v1(1,1,1) et v2(2,2,2).

    Si * est l'opérateur de produit scalaire, alors v1*v2 donne 6.

    je peux faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    vec v3;
    v3 = v1*v2;
    cout << v3 << endl;

    mais je ne peux pas faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    cout << v1*v2 << endl;
    sans avoir d'erreur à la compilation. Ce que je comprends c'est que le compilateur ne sait pas s'il doit appliquer l'opérateur '<<' avant ou après l'opérateur '*' dans l'instruction.

    Comment coder des règles de priorités entre les opérateurs surchargés ?


    voici la partie "concernée" par le problème, de la classe :


    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
     
    class vec
    {
    private :
    vector<double>c;
     
    public:
    vec();												
    vec(const double c0, const double c1, const double c2);
     
    //accesseurs en lecture/ecriture
    double & operator()(unsigned int);
    double   operator()(unsigned int ) const;
     
    //opérateurs surchargés
    vec operator+(const vec &) const;
    vec operator*(const double ) const;
    double operator*(const vec &)   const;
    vec operator^(const vec &) const;
    vec operator/(const double ) const;
    operator /vec & operator+=(const vec &);
     
    friend ostream  & operator<<(ostream &, const vec &);
    };

    Bien sûr je peux mettre des parenthèses autour de (v1*v2), mais je ne veux pas...


    Merci,
    A+
    --
    Heimdall

  2. #2
    Membre émérite
    Avatar de Franck Dernoncourt
    Homme Profil pro
    PhD student in AI @ MIT
    Inscrit en
    Avril 2010
    Messages
    894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : PhD student in AI @ MIT
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 894
    Points : 2 464
    Points
    2 464
    Par défaut
    Citation Envoyé par Heimdall
    Le compilateur ne sait pas s'il doit appliquer l'opérateur '<<' avant ou après l'opérateur '*' dans l'instruction.
    Si : http://en.wikipedia.org/wiki/Operato...tor_precedence
    An operator's precedence is unaffected by overloading.

  3. #3
    screetch
    Invité(e)
    Par défaut
    toujours mettre l'erreur du compilateur

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    1/ On ne peut pas modifier la priorité des opérateurs

    2/ Avec l'opérateur * cela marche très bien car l'opérateur * est bien plus prioritaire :
    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
    #include <iostream>
    class vec
    {
    private :
     
    public:
        vec operator*(const vec &) const{return *this;}
     
        friend std::ostream  & operator<<(std::ostream &, const vec &);
    };
     
    std::ostream  & operator<<(std::ostream &o, const vec &)
    {
        return o;
    }
     
    int main()
    {
        vec v1,v2;
        vec v3;
     
        v3 = v1*v2;
        std::cout << v3 << std::endl;
        std::cout << v1*v2 << std::endl;
     
        return 0;
    }
    3/ L'opérateur ^, il faut parenthéser car l'opérateur est - prioritaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <iostream>
     
    int main()
    {
        int i,j;
        std::cout<<i^j<<std::endl; // erreur
        std::cout<<(i^j)<<std::endl; // OK
     
        return 0;
    }
    4/ L'interface de ta classe est très perturbante. Il est assez peu intuitif de comprendre tes surcharges :

    5/ On essaie en générale de garder une sémantique usuelle pour les surcharges d'opérateurs. Pour la surcharge de l'opérateur * avec 2 vecteurs, je me demanderai toujours si c'est un produit scalaire, un produit vectoriel... Bref, pas bonne idée : autant donner un nom de fonction explicite. L'opérateur, c'est bien pour un vecteur par un scalaire car il n'y a pas d’ambiguïté.

  5. #5
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut
    Re,

    en effet, je ne sais pas pourquoi mais le v1*v2 a marché... j'ai du réver et confondre avec la ligne qui testait le produit vectoriel.

    Pour ce qui est de l'interface... en fait perso le '^' m'allait bien car en france, il correspond au même symbole que symbole mathématique de produit vectoriel.
    Dans les notations anglophones, c'est le 'x' (cross-product) mais qui n'existe pas ici...

    Pour ce qui est du produit scalaire, pareil on ne peut pas surcharger le '.', qui est la notation mathématique usuelle... j'ai donc choisi le '*'.


    Avant je voulais faire ceci :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    double operator*(const vec &) const; // produit scalaire
    vec operator*(const vec &) const;     // produit vectoriel

    i.e. surcharger deux fois l'opérateur '*' pour que, lorsqu'on fasse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    vec v1, v2, v3;
    double a;
     
    v1 = v2*v3;
    a = v2*v3;

    on utilise l'un ou l'autre.... mais ça ne passe pas à la compilation, je ne comprends pas trop pourquoi... le compilateur devrait savoir quel opérateur utiliser en regardant la variable ('a' ou 'v1') qui se trouve a gauche de l'opérateur... mais non...


    Personnellement, j'aime bien faire des opérations mathématiques avec mes vecteurs sans qu'il n'apparaisse de nom de fonction dans mon code, je trouve ça plus "joli".

    Dans le code d'une formule :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    double a;
    vec v1, v2;
     
    a = v1*v2;
    il n'y a de toute façon pas d'ambiguité, si 'a' est un scalaire, le '*' ne peut être qu'un produit scalaire...
    --
    Heimdall

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class vec;
    std::ostream& operator<<(std::ostream&,vec const&);
    // existe déjà  std::ostream& std::ostream::operator<<(double);
     
    // ....
    vec v1;
    vec v2;
     
    std::cout<<v1*v2<<"\n";
    Produit vectoriel ? Produit scalaire ? Produit tensoriel ? etc.

  7. #7
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut
    ok en effet, j'ai rien dit...

    Et si c'est marqué dans la doc que c'est un produit scalaire, c'est pas suffisant ?

    Parce que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    cout << v1.dot(v2) << endl;
    est très moche...

    ou alors faire une fonction amie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    cout << DotProduct(v1, v2) << endl;

    Mais dans les grosses formules, ça devient un peu illisible :

    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
     
    vec j, B, v;
    double a;
     
    // je prefere ca ...
     
    a = (j^B)*v;
     
    // que ca...
     
    a = DotProduct(VectorProduct(j,B), v);
     
     
    // meme si 
     
    cout << j*B << endl;
     
    // n'est pas evident a lire sans avoir lu la doc de 'vec'

    mais après je suis dans l'impasse car j'ai effectivement besoin d'ajouter le produit tensoriel, et je suis un brin a court de "symboles"... vais-je etre obligé d'utilisée des fonctions amies et avoir des grosses formules moches ?
    --
    Heimdall

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Je ne suis pas un expert en bibliothèque mathématique. Mais j'ai regardé par curiosité 2 ou 3 d'entre elles. Et elles confirment ce que je te dis : les opérateurs sont délaissés dans ces cas pour des fonctions au nom explicit (dot, etc.).
    Qui plus est, le produit vectoriel n'est ni commutatif ni associatif. Ce qui n'est pas le cas de * sur des scalaires.
    Plus je creuse, plus je trouve des arguments contre la surcharge des opérateurs dans ce sens

  9. #9
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut
    Et ils font ça a base de fonctions amies comme je disais ? Je suis sceptique mais c'est encore la solution que je préfère par rapport à une méthode de la classe vec dont je trouve l'ecriture très peu symétrique (même si le produit vectoriel n'est pas commutatif).

    Tu m'as sûrement convaincu tout de même... surtout comme je disais, que pour le produit tensoriel je suis a court d'opérateur, donc autant tout faire avec des fonctions amies.

    Merci des conseils !
    --
    Heimdall

Discussions similaires

  1. Priorité des opérateurs surchargés dans un cas ambigu
    Par armapython dans le forum Général Python
    Réponses: 9
    Dernier message: 21/05/2014, 12h30
  2. [OCaml & F#] Priorité des opérateurs
    Par SpiceGuid dans le forum Caml
    Réponses: 7
    Dernier message: 01/01/2008, 15h00
  3. priorité des opérateurs
    Par new_wave dans le forum SQL
    Réponses: 13
    Dernier message: 08/11/2007, 21h44
  4. Priorité des opérateurs
    Par neuromencien dans le forum Langage
    Réponses: 3
    Dernier message: 14/05/2007, 17h06
  5. Réponses: 3
    Dernier message: 31/08/2006, 10h39

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