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 :

variable en lecture seule


Sujet :

C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre � l'essai
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    D�cembre 2011
    Messages
    5
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : D�cembre 2011
    Messages : 5
    Par d�faut variable en lecture seule
    bonjour,

    je viens de voir cette id�e dans un forum pour obtenir une variable en lecture seule sans utiliser de getter:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        class A
        {
        public:
            const int & Value;
            A() : Value( value_ )
            {
            }
        private:
            int value_;
        };
    si j'ai bien compris, il s'agit d'utiliser un type "r�f�rence vers une donn�e constante", alors que la donn�e (value_) ne l'est pas...

    Est-ce vraiment possible?

  2. #2
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,
    Citation Envoy� par airstrike Voir le message
    bonjour,

    je viens de voir cette id�e dans un forum pour obtenir une variable en lecture seule sans utiliser de getter:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        class A
        {
        public:
            const int & Value;
            A() : Value( value_ )
            {
            }
        private:
            int value_;
        };
    si j'ai bien compris, il s'agit d'utiliser un type "r�f�rence vers une donn�e constante", alors que la donn�e (value_) ne l'est pas...

    Est-ce vraiment possible?
    A priori, c'est possible, mais cela n'ira pas sans poser un probl�me, du moins tel que ton code est pr�sent� :

    value_ n'est pas initialis�, et vaut donc "n'importe quoi"(en fait, les r�sidus d'une utilisation ant�rieur de la m�moire ) , et, comme tu ne fournit rien permettant donner une valeur correcte � value_... tu n'iras pas tr�s loin

    Maintenant, il faut quand meme se poser certaines question : pourquoi veux tu �viter le recours � un accesseur, et, surtout, as tu -- seulement -- besoin d'acc�der � ce membre

    Comme on travaille en orient� objet, on a l'habitude d'appeler des fonctions sur nos objets, et rien ne t'emp�che d'�crire 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
        class A
        {
        public:
            /* pour ce qui est des types primitifs, le recours aux références
             * ne se justifie réellement que quand c'est une référence non
             * constante...
             * 
             * autrement, la copie ne prend pas plus de temps, et évite une
             * indirection dans le binaire généré ;) 
             *
             */
            int value() const { return value_;}
        private:
            int value_;
        };
    int main()
    {
        A a;
       a.value();
       /* ... */
       return 0;
    }
    Mais la question essentielle est surtout : as tu besoin d'acc�der � cette valeur

    La grande id�e qui soutend au principe OO, c'est que l'on pense � nos types non plus en terme d'ensemble de donn�es repr�sentant quelque chose de particulier, mais bien en terme d'un objet susceptible de nous fournir un certain nombre de services.

    Les services attendus de la part de nos objets vont essentiellement d�pendre de la responsabilit� que l'on souhaite leur donner (n'oublie pas le principe de la responsabilit� unique, qu'il est vraiment important de garder toujours en tete )

    Par exemple, il semblerait logique de placer des accesseurs (mais pas des mutateurs ) dans une classe R�servoir (de carburant ), car sa responsabilit� serait de ... me permettre de repr�senter des informations concr�tes sur ce r�servoir:
    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
    class Reservoir
    {
        public:
            Reservoir(double max):qte_(0),max_(max){}
            double qte() const{return qte_;}
            double maxQte() const{return max_;}
            double status() const{retutrn qte_/ max_;}
            bool empty() const{return qte_ == 0;}
            bool full() const {return qte_ == max_;}
            double fullfill() 
            {
                double temp = max_ - qte_; 
                add(temp);
                return temp; 
            }
            void add(double howMuch)
            {
                assert(qte_+ howMuch <= max_);
                qte_+= howMuch;
            }
            void remove(double howMuch)
            {
                qte_-= howMuch;
            }
        private:
            double qte_;
            double max_;
    };
    Mais cette classe ne vaut que par l'usage qui en sera fait!!!!

    En l'occurrence, elle sera sans doute plac�e dans une classe voiture (voire dans une classe "Vehicule � moteur" ).

    On est bien conscient du fait qu'une voiture va disposer d'un r�servoir � carburant, mais, � moins d'�tre m�canicien, tu ne devras jamais avoir acc�s au r�servoir en tant que tel : ce sont les services rendus par la voiture qui iront manipuler le r�servoir

    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
    class Voiture
    {
        public:
            bool hasFuel() const{return !tank_.empty();}
            bool needRefuel() const{return tantk_.status() <= 0.25;}
            bool hasFilledTank() const{return tank_.full();}
            double tankStatus() const {return tank.status();}
            double fullFill(){return tank_.fullFill();}
            void addFuel(double qte){tank_.add(qte);}
            /* il y a tous les autres services qui peuvent, pourquoi pas, 
             * modifier l'état du réservoir :D
             */
        private:
            Reservoir tank_;
           /* un tas d'autre choses :D */
    }
    L'id�e mise en avant ici, c'est que l'on n'a pas besoin de connaitre la classe r�servoir pour pouvoir utiliser la classe voiture ( c'est d'ailleurs une loi � appliquer en OO : la loi demeter )

    D'ailleurs, si je n'avais pas cr�� ma classe r�servoir, j'aurais tr�s bien pu m'en passer dans ma classe voiture! : le fait que la classe Voiture utilise une instance de la classe R�servoir est devenu... un d�tail d'impl�mentation qui peut �tre totalement ignor� de l'utilisateur

    Il n'y a donc aucune raison de permettre � l'utilisateur d'acc�der directement � l'instance de r�servoir qui est utilis� par une instance de voiture
    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

  3. #3
    Membre chevronn�

    Inscrit en
    Ao�t 2007
    Messages
    300
    D�tails du profil
    Informations forums :
    Inscription : Ao�t 2007
    Messages : 300
    Par d�faut
    Les conseils de Koala01 sont � m�diter, mais si la question portait simplement sur la cosm�tique d'acc�s � une valeur (lancer une fonction qui renvoie une valeur, ou utiliser la valeur directement), alors la r�f�rence sur constante marche parfaitement. Comme dit ci-dessus, il faut initialiser la valeur, mais c'est vrai pour un "getter" aussi.

    Cependant, ind�pendamment des remarques de Koala01, il faut bien comprendre qu'une r�f�rence sur constante pr�sente quelques minuscules avantages cosm�tiques ou situationnels (�criture naturelle, possibilit� d'utiliser l'adresse), au prix d'une �norme contrainte sur la classe qui est r�dhibitoire dans un tr�s grand nombre de situations: pas de constructeur de copie, interdiction de d�placer l'instance en m�moire, et tout ce qui en d�coule (incompatibilit� avec pratiquement toute la STL).

    Donc pour ces deux s�ries d'objections (celles au niveau du concept �num�r�es par Koala01, et celles de bas niveau dues � l'impl�mentation), je vous d�conseille fortement cette technique.

  4. #4
    Membre chevronn� Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Par d�faut
    @ac_wingless je trouve ton message fort int�ressant:
    il faut bien comprendre qu'une r�f�rence sur constante pr�sente quelques minuscules avantages cosm�tiques ou situationnels
    Pour moi des qu'un param�tre de ma fonction n'est plus de type simple je le passe en r�f�rence const, pour �vit� une recopie.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    int fonction(int typSimple, const std::string& typeNonSimple)
    pas de constructeur de copie
    J'ai construit cette exemple qui fonctionne, j'ai rat� un truc ?
    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>
    #include <vector>
     
     class A
        {
        public:
            const int & Value;
            A(int v) : value_(v), Value( value_ )
            {
            }
        private:
            int value_;
    		friend std::ostream& operator<<(std::ostream& o, const A& a) { o << a.value_ ; return o ; }
        };
     
    int main()
    {
    	A a(123);
    	A aa(a);
    	std::cout << aa << std::endl ;	
    }
    interdiction de d�placer l'instance en m�moire
    Genre faire un memcpy sur une instance? Perso je fais jamais cela.
    incompatibilit� avec pratiquement toute la STL
    Oui en effet sans bien comprendre pourquoi cela ne fonctionne pas
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    	A a(123);
    	std::vector<A> v ;
    	v.push_back(a);
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    'operator =' function is unavailable in 'A'
    Bon on peut s'en sortir avec des pointeurs et des references...
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    	A a(123);
    	std::vector<A*> v ;
    	v.push_back(&a);
    	std::cout << *(v[0]) << std::endl ;
    Pour finir en revenant sur la question pos�e je pense que l'utilisation des accesseurs est moins d�routante, penser au suivant d�veloppeur qui va reprendre le code. Mais elle est loin d��tre b�te!

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    Citation Envoy� par themadmax Voir le message
    Genre faire un memcpy sur une instance? Perso je fais jamais cela.
    On fait du C++ ici que diable, pas besoin de memcpy, la copie par d�faut suffit dans beaucoup de cas.

    Citation Envoy� par themadmax Voir le message
    Oui en effet sans bien comprendre pourquoi cela ne fonctionne pas
    Parce que lorsqu'une classe a une r�f�rence comme membre, la copie par d�faut n'est pas d�finie par le compilateur, car une r�f�rence ne peut plus �tre modifi�e une fois initialis�e.

  6. #6
    Membre chevronn� Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Par d�faut
    Parce que lorsqu'une classe a une r�f�rence comme membre, la copie par d�faut n'est pas d�finie par le compilateur, car une r�f�rence ne peut plus �tre modifi�e une fois initialis�e.
    D'apr�s mes tests sous vc et g++, on dirait bien qu'un constructeur par copie est bien d�finis...
    Pour avoir un code fonctionnelle avec les STL il faut surcharger l�op�rateur d'affectation:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    A& operator=(const A& a) { _value = a._value; return *this;}

Discussions similaires

  1. [C++] Variable Membre en lecture seule
    Par CR_Gio dans le forum C++
    R�ponses: 8
    Dernier message: 18/12/2007, 11h05
  2. variable globale en lecture seule
    Par kromartien dans le forum C
    R�ponses: 4
    Dernier message: 22/09/2007, 16h23
  3. [TQuery][DBGRID] pb de mise � jour: table en lecture seule
    Par Chryst�le Carr� dans le forum Bases de donn�es
    R�ponses: 3
    Dernier message: 24/11/2003, 09h36
  4. R�ponses: 5
    Dernier message: 28/10/2003, 15h01
  5. [firebird] Connexion impossible en lecture seule
    Par severine dans le forum Administration
    R�ponses: 2
    Dernier message: 01/08/2003, 15h35

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