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 :

Const et priorité de fonction


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 56
    Points : 38
    Points
    38
    Par défaut Const et priorité de fonction
    Bonjour à tous,

    J'ai un petit soucis d'ordre technique auquel je ne trouve pas de réponses sur le net.
    J'aimerai gérer la priorité des fonctions dans une classe. Ça sera plus simple à expliquer avec l'exemple suivant :
    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
    #include <iostream>
     
    class Test
    {
    	private:
    		int a[255] ;
     
    	public:
    		inline int& operator[](int index) { printf("No const\n"); return a[index]; }
    		inline const int& operator[](int index) const { printf("Const\n"); return a[index]; }
    } ;
     
    int main()
    {
    	Test x ;
    	x[0] = 100 ;
    	printf("%i\n", x[0]) ;
    	printf("%i\n", ((const Test)x)[0]) ;
     
    	return 0 ;
    }
    Et voici le résulat de l'execution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ ./test_priority
    No const
    No const
    100
    Const
    100
    Dans cet exemple, j'ai 2 fonctions pour l'opérateur [], une qui gère en constante, et l'autre sans constante.

    Dans le cadre d'un développement d'API, j'aimerai faire en sorte que, par défaut, ce soit la fonction constante qui soient appelé. SAUF quand on s'en sert pour une affectation.
    En gros, j'aimerai que x[0]=100 appelle la fonction non constante, et printf("%i\n", x[0]) la fonction constante, sans pour autant devoir caster comme dans le second printf.

    Est-ce possible ??
    Merci beaucoup.

  2. #2
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Si tu veux distinguer lecture et écriture, il faut passer par un proxy. Le résultat ne sera toutefois pas parfait.
    Un item entier de More Effective C++ y est consacré dans mes souvenirs.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

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

    Informations professionnelles :
    Activité : aucun

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

    Le propre d'un programme est d'être plus complexe que cette "malheureuse" fonction main.

    Tu ne manqueras donc surement pas d'occasion de définir des méthodes qui prendront une référence sur un objet de type Test en paramètre, ou qui renverront une telle référence.

    C'est à ce point que la constance va apporter toute sa puissance:

    Si la fonction que tu définis prend une référence constante, tu ne pourra pas assinger une nouvelle valeur à ton arg[n], alors que tu pourra le faire si la fonction prend une référence non constante.

    De la même manière si la fonction que tu écrit renvoie une référence constante, le compilateur se plaindra déjà bien avant l'exécution si tu venais à envisager un code 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    /* si le retour de cette fonction n'était pas constant
     * le compilateur se plaindrait de la perte de constance, étant donné
     * que arg est une référence constante
     */
    const Test& foo(const Test& arg) 
    {
        /*...*/
        return arg;
    }
    int main()
    {
        Test t;
        /* t n'est pas constant, c'est donc la version non constante
         * qui est appelée
         */
        t[0]=5;
        /* par contre, le retour de foo est constant...
         * le compilateur refuse donc l'écriture de
        foo(t)[0] = 5;
        /* par contre, il accepte sans problème */
        cout<foo(t)[0];
        return 0;
    }
    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

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    La règle pour résoudre la surcharge entre fonction membre const et non const consiste uniquement à regarder si l'objet sur lequel cette fonction est appelée est constant ou pas.

    Tu aimerais que cette règle se base sur la façon dont le retour de la fonction va être utilisé, ce qui n'est possible qu'avec le proxy dont parle Luc.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 896
    Points : 1 912
    Points
    1 912
    Par défaut
    Il me semble qu'un de mes prof m'avait dit que par défaut c'est la méthode non-constante qui est prise, que la version const n'est appelée que pour les objets const et pointeurs d'objets const. Par ailleurs, const sert à vérifier à la compilation qu'une fonction supposée constante ne modifie pas l'objet, mais n'apporte pas de sécurité à l'exécution.

    Peut-être que tu peux lever l'ambiguïté comme-ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    inline int& operator[](int index) { printf("No const\n"); return a[index]; }
    inline int operator[](int index) const { printf("Const\n"); return a[index]; }
    Mais bon, à vérifier.

    Citation Envoyé par koala01 Voir le message
    Ca ne devrait pas plutôt être :

    ?

    Par curiosité, qu'est-ce-que c'est un proxy (dans ce contexte, je veux dire), un design pattern ?

  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
    La question me paraît étrange: vas-tu avoir un comportement différent entre la version const et l'autre? Peux-tu expliciter ton cas, car je n'ai jamais vu d'exemple de ce genre. Sinon, à partir du moment où c'est le même comportement, que t'importe de savoir laquelle des deux est appelée. La version non const est en général celle dont on a besoin la plus part du temps, la version const sert à pouvoir accéder aux propriétés avec un objet const tout en garantissant que celles-ci conserveront le caractère const (uniquement à la compil, bien sûr).

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    L'idée, c'est que la version non constante ne retourne pas une référence à un int, mais une classe qui ressemble à une telle référence, mais fera des choses supplémentaires.

    Quand tu récupères une référence/proxy, tu ne sais pas si c'est pour la lire, ou l'écrire. Il est donc trop tôt pour prendre une décision à ce moment là. C'est au moment où tu utilises cette référence/proxy (par exemple, d'en l'opérateur = de ta classe de proxy) que tu sais ce que l'utilisateur va en faire.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    La question me paraît étrange: vas-tu avoir un comportement différent entre la version const et l'autre? Peux-tu expliciter ton cas, car je n'ai jamais vu d'exemple de ce genre.
    Le différence est entre un accès en lecture et un accès en écriture à l'objet (et utiliser const pour ça ne marche justement pas). Par exemple, on peut imaginer que quand on accède en écriture à l'objet, il mets à jour un flag dirty afin de se sauver quand on quitte le programme.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 896
    Points : 1 912
    Points
    1 912
    Par défaut
    Quelque chose dans ce genre ?

    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
     
    class PosInt  // Protège un entier pour qu'il soit toujours >= 0
    {
    private:
        int & _ward;
    public:
        PosInt(int & ward) : _ward(ward) { if(_ward < 0) _ward = 0;}
     
    friend int & operator=(int & i, const PosInt & pi);
    friend PosInt & operator=(PosInt & pi, const int i);
    };
     
    int & operator=(int & i, const PosInt & pi) { return i = pi._ward; }
     
    PosInt & operator=(PosInt & pi, const int i)
    {
        if(i < 0)  // Absorbe les valeurs négatives
            pi._ward = 0;
        else
            pi._ward = i;
        return pi;
    }

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Pourquoi pas, sauf que dans le cas en question, le proxy gardera probablement en plus une référence vers le conteneur d'où il vient, afin de pouvoir communiquer avec lui.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

Discussions similaires

  1. Perdu dans la priorité des fonctions
    Par Dev222 dans le forum Langage
    Réponses: 2
    Dernier message: 18/08/2013, 11h42
  2. Problème de fonction "const" avec une std::map
    Par Clad3 dans le forum SL & STL
    Réponses: 3
    Dernier message: 02/01/2007, 12h38
  3. Réponses: 3
    Dernier message: 13/07/2006, 00h51
  4. liste énumérée de const. perso comme paramètre de fonction
    Par batou22003 dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 13/12/2005, 20h37
  5. appel de fonction const
    Par pseudemys dans le forum C++
    Réponses: 5
    Dernier message: 15/02/2005, 23h12

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