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 :

Passage par r�f�rence


Sujet :

C++

  1. #1
    Membre �clair�
    Homme Profil pro
    �tudiant
    Inscrit en
    Septembre 2011
    Messages
    412
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Septembre 2011
    Messages : 412
    Par d�faut Passage par r�f�rence
    Bonjour,
    J'ai un probl�me de compr�hension � propos des passages par r�f�rence. Je suis en train de travailler sur les classes abstraites. Voici ma classe CExcFille qui permet de cr�er n'importe quel code erreur gr�ce au constructeur CExcFille :

    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
    namespace
    {
        class CExcFille : public CException
        {
            public :
            inline void _Edit()
            {
                cout << "Affichage de la fonction _Edit (class CEXcFille)" << endl;
            }
     
            CExcFille(const string & Libelle, const unsigned CodErr)
            {
     
            }
        };
    }
    Je voudrais comprendre pourquoi l'on passe le param�tre Libelle en r�f�rence alors que le CodErr non ?

    Deuxi�mement, j'ai une classe CEditable qui me permet d'afficher n'importe quel flux via l'op�rateur << :

    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
    namespace nsUtil
    {
        class CEditable
        {
            public :
            virtual std::ostream & operator << (std::ostream & os,
                                    const CEditable & Obj)
     
            {
                     return Obj._Edit(os);                  
            }
            virtual std::ostream _Edit( const std::ostream & os) =0;
            virtual ~CEditable (void);
        };
     
    } 
     
     
    {
        class CExcFille : public CException
        {
            public :
     
            inline virtual ostream &  _Edit (ostream & os)
            {
                return os << "Affichage de la fonction _Edit (class CEXcFille)" << endl;
            }
     
            CExcFille(const string & Libelle, const unsigned CodErr) : CException(Libelle,CodErr) {}
     
        };
    Je ne comprends pas pourquoi la fonction renvoi un ostream et pourquoi est-il en r�f�rence ?

    De m�me pour ces deux op�rateurs, pourquoi l'un prend une r�f�rence et l'autre non ?
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
            CDuree & operator ++ (void)                            throw ();
            CDuree   operator ++ (int)                             throw ();

    Merci de votre aide !

  2. #2
    Expert confirm�
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 772
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 772
    Par d�faut
    Simple
    • Passage par valeur -> 1 recopie/ appel du constructeur par recopie (*)
    • Passage par r�f�rence -> 0 recopie (*)
    • Retour r�f�rence -> Cha�nage puisque le passage est par r�f�rence (**)


    * -> Donc pour des POD (Plain Old Data) (***) on s'en fiche de la recopie.
    Par contre, pas pour un object. Note la r�f�rence constante pour dire qu'on ne veut pas le modifier.

    ** -> Exemple: a = b + c + d
    Cela va d�pendre de l'ordre mais en gros cela donne b.operator+ ( c.operator+ (d) ).

    �dit: @Bousk, *** Effectivement dans les POD il y a les "petites" struct/ class

  3. #3
    Membre Expert
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    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 : 760
    Par d�faut
    Concernant les op�rateurs ++:
    - la pr�-incr�mentation (T & operator++() / ++i) permet d'incr�menter un objet puis retourne une r�f�rence sur lui m�me.
    - la post-incr�mentation(T operator++(int) / i++) fournit la valeur de l'objet (copie) et incr�mente l'original.

    C'est exactement le m�me comportement que les types h�rit�s du C (int, etc),

  4. #4
    R�dacteur/Mod�rateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : Canada

    Informations professionnelles :
    Activit� : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par d�faut
    Citation Envoy� par foetus Voir le message
    * -> Donc pour des POD (Plain Old Data) on s'en fiche de la recopie.
    Pardon ?
    Seuls les �l�ments primitifs/de base (char, int, ..) devraient �tre pass�s par copie, et certainement pas les POD. Un POD �a peut �tre cons�quent, et y'a aucun int�r�t � le copier dans tous les sens sauf � savoir ce qu'on fait.
    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
    Expert �minent

    Femme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par d�faut
    En plus dans ton exemple, + �tant associatif "left-to-right", ton exemple de chainage est en fait:

    a = b + c + d �quivaut � : a.operator=( operator+( operator+(b, c) , d) ).
    Et ca n'illustre pas le chainage, car en g�n�ral, + n'est pas une fonction membre.

    Suppose une classe Assignment (inspir�e de boost::assign)
    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 <list>
    template<typename Collection, typename Value>
    class Assignment {
    private:
        Collection& ref;
     
    public:
        Assignment(Collection& ref, Value const& v) : ref(ref) {operator,(v);}
        Assignment& operator,(Value const& v) {ref.push_back(v); return *this;}
    };
     
    template<typename Collection, typename Value>
    Assignment operator+=(Collection & c, Value const& v) {
        return Assignment(c), v;
    }
     
    int main() {
        std::list<int> l;
        l+=1, 2, 3;
        return 0;
    }
    La derni�re instruction, l+=1, 2, 3;, se parenth�se ainsi: ((l+=1), 2), 3;.
    Ca forme d�velopp�e est en fait:
    operator+=(l, 1).operator,(2).operator,(3);.

    PS: J'aime bien cet exemple, on y trouve plein de chose sympa: Proxy, cha�nage, template. Par contre, la vraie biblioth�que est plus complexe, plus complete, et plus s�re

  6. #6
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de caf�
    Inscrit en
    Mai 2007
    Messages
    1 050
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 39
    Localisation : France

    Informations professionnelles :
    Activit� : Consommateur de caf�
    Secteur : High Tech - Multim�dia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 050
    Par d�faut
    Seuls les �l�ments primitifs/de base (char, int, ..) devraient �tre pass�s par copie, et certainement pas les POD
    Je ne serait pas aussi radical. Tout d�pend du sizeof de ton POD. Un POD de 2*sizeof(int) est tout � fait copiable sans avoir de surcout par rapport � une mise en r�f�rence.

  7. #7
    Membre Expert

    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
    Billets dans le blog
    21
    Par d�faut
    1. Le passage par r�f�rence est utile pour ne pas copier les objets "lourds". Dans le cas des types num�riques natifs (int, float, char, etc.), une copie ne co�te pas suffisamment pour qu'on le passe par r�f�rence, il suffit donc de la passer par valeur. Cela dit, lorsqu'on passe l'argument par valeur, il n'est pas n�cessaire de le d�clarer const.

    2. On retourne ostream& par r�f�rence pour le cha�nage, en effet:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    std::cout << 'a' << 'b' << 'c';
    �quivaut �

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    ((std::cout << 'a') << 'b') << 'c';
    3. Du coup on passe le caract�re 'c' au flux renvoy� par le passage du caract�re 'b' au flux renvoy� par le passage de 'a' � std::cout.

    4. Pour l'incr�mentation, apr�s ou avant, si tu y r�fl�chis, tu verras que la diff�rence correspond au comportement d�sirable:
    post-incr�mentation: tu retournes la valeur actuelle et incr�mentes
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    int x = 0;
    std::cout << x++; // 0
    std::cout << x; // 1
    Du coup si tu retournais une r�f�rence, le premier cout << afficherait d�j� 1, ce qui est contraire � la s�mantique de l'op�rateur...

  8. #8
    Membre �clair�
    Homme Profil pro
    �tudiant
    Inscrit en
    Septembre 2011
    Messages
    412
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Septembre 2011
    Messages : 412
    Par d�faut
    Bonsoir,
    merci pour vos explications, cependant, je n'ai toujours pas compris pourquoi dans l'operateur :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    CDuree   operator ++ (int)                             throw ();
    on a un int en param�tre, alors que lorsque l'on fait i++, on ne sp�cifie pas de param�tre. De m�me, dans le premier op�rateur, si je suis ma logique (qui n'est pas la meilleure ), �tant donn� qu'il y a un void, j'ai tendance � penser que �a correspond au i++, pourquoi ce n'est pas le cas ?


    Deuxi�mement, je n'ai toujours pas compris pourquoi dans la fonction :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
            virtual std::ostream & operator << (std::ostream & os,
                                    const CEditable & Obj)
    On sp�cifie un param�tre os.

    Merci pour vos r�ponses !

  9. #9
    Expert confirm�
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 772
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 772
    Par d�faut
    Regarde la page Wiki: Operators in C and C++

    R�ponse 1:
    Note: C++ uses the unnamed dummy-parameter int to differentiate between prefix and suffix increment operators.
    �dit: Cela semble ultra-logique
    Comme il n'y a qu'un seul op�rateur alors ++a -> a.operator++() et a++ -> a.operator++().
    Donc tu es chocolat

    Et puisque tu vas le demander, en th�orie, une signature d'une m�thode/ fonction ne prend pas en compte le type de retour (juste les types des param�tres + le nom de la m�thode/ fonction) donc impossible de les d�partager avec un type de retour diff�rent.

  10. #10
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de caf�
    Inscrit en
    Mai 2007
    Messages
    1 050
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 39
    Localisation : France

    Informations professionnelles :
    Activit� : Consommateur de caf�
    Secteur : High Tech - Multim�dia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 050
    Par d�faut
    on a un int en param�tre, alors que lorsque l'on fait i++, on ne sp�cifie pas de param�tre. De m�me, dans le premier op�rateur, si je suis ma logique (qui n'est pas la meilleure ), �tant donn� qu'il y a un void, j'ai tendance � penser que �a correspond au i++, pourquoi ce n'est pas le cas ?
    Tu ne peux pas te baser sur le type de retour d'une fonction car en C++ le type de retour ne fait pas partie de la signature de la fonction. Ce qui fait la signature de la fonction sont : le nom de la fonction, les param�tres de la fonction et rien d'autre. Voila pourquoi si tu fais deux fonctions identiques avec deux types de retour diff�rents ton compilateur te diras qu'il ne sait pas laquelle choisir car il ne regarde pas le type de retour pour savoir quelle fonction appeler mais le nom et les param�tres uniquement.

    Ensuite pour le i++ � un param�tre car le compilateur va faire ceci:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    int int::operator(int& i) //this en paramètre
    {
        int i_retour = i;
        i = i +1;
        return i_retour;
    }
    Il incr�mente ton i et retourne la valeur avant incr�mentation.

    Pour le ++i il n'y a pas de param�tre car:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    int int::operator() //pas de paramètre
    {
        return this+1;
    }
    Il incr�mente ton i et retourne "this" (ta valeur incr�ment�e)

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Passage par r�f�rence
    Par e1lauren dans le forum D�buter avec Java
    R�ponses: 4
    Dernier message: 01/09/2006, 12h59
  2. Passage par copie vs passage par r�f�rence
    Par bolhrak dans le forum C++
    R�ponses: 11
    Dernier message: 20/08/2006, 23h37
  3. R�ponses: 4
    Dernier message: 26/12/2005, 17h01
  4. Passage par r�f�rence
    Par difficiledetrouver1pseudo dans le forum Langage
    R�ponses: 9
    Dernier message: 28/09/2005, 11h17
  5. Probl�me tr�s rapide de passage par r�f�rence
    Par Noxexplorer dans le forum ASP
    R�ponses: 2
    Dernier message: 23/06/2005, 10h02

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