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 :

débutant : question technique sur transtypage


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut débutant : question technique sur transtypage
    Bonjour,
    je suis débutant et ai écrit le programme suivant (j'ai laissé les parties de code qui nous intéressent) :
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    #include <cstdlib>
    #include <iostream>
    #include <string.h>
     
    using namespace std;
    /****************** class chaine ****************
    *************************************************/
    class chaine
    {
          public:
                 chaine(const char* _val);
          private:
                  int longueur;
                  char* val;
    };
     
    chaine::chaine(const char* _val)
    {
        longueur=strlen(_val);
        val=new char[longueur+1];
        strcpy(val,_val);
    }
     
     
    /********************* class pile-chaine **************
    *******************************************************/
    class pile_chaine
    {
          public:
     
              int empiler(const chaine& chn);
              pile_chaine& operator=(const pile_chaine& op2);
          private:
              int max;
              enum pile_etat{ok,plein,vide};
              chaine* table;
              int nb_elem;
              pile_etat etat;
    };
     
     
     
    int pile_chaine::empiler(const chaine& chn)
    {}
     
     
    int main(int argc, char *argv[])
    {
        pile_chaine tab_chaine(5);
        tab_chaine.empiler("test1");
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    Ce programme accepte le transtypage dans le programme principal, c'est à dire que "tab_chaine.empiler("test1") fonctionne et l'argument formel "const chaine& chn" de "int pile_chaine::empiler" s'initialise grace au constructeur de transtypage défini au début.

    J'ai essayé avec une modification suivante (je note ici uniquement les lignes où j'ai changé quelque chose) :

    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 pile_chaine
    {
          public:
     
              int empiler(chaine& chn);
          private:
              ..........
    };
     
     
     
    int pile_chaine::empiler(chaine& chn)
    {}
    int main(int argc, char *argv[])
    {
        pile_chaine tab_chaine(5);
        tab_chaine.empiler("test1");
        .............
    }
    le seul changement que j'ai fait est de remplacer l'argument constant formel ("const chaine& chn") de "int pile_chaine::empiler" en un argument non constant ("chaine& chn") et à la compilation j'ai l'erreur suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    169 C:\Dev-Cpp\programme1-main.cpp no matching function for call to `pile_chaine::empiler(const char[6])' 
     note C:\Dev-Cpp\programme1-main.cpp:114 candidates are: int pile_chaine::empiler(chaine&)
    Est-ce que quelqu'un peut m'expliquer pourquoi le transtypage ne fonctionne plus. Merci d'avance.
    Xavier

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Parce que tu ne peux pas créer de référence non constante sur un temporaire. Pourquoi ta fonction ne prend-elle pas une référence constante ?

  3. #3
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Lorsque tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    tab_chaine.empiler("test1");
    Le compilateur cherche une méthode 'empiler' dans 'pile_chaine' dont la signature correspond aux arguments passés.
    Il n'en trouve pas directement puisque la méthode prend un 'chaine&' et que tu lui passes un 'const char*'.
    Ca explique l'erreur de compilation.

    Pourquoi ça compilait avant avec le 'const chaine&' dans 'empiler' ?
    En fait, dans la tentative de résolution de l'appel de méthode, le compilateur essaye en plus de construire implicitement un objet 'chaine' à partir de l'argument 'const char*'.
    Par contre cet objet 'chaine' doit être 'const' car construit sur la pile au moment de l'appel.

    Pour que ça fonctionne il faut que tu fasses par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    int main(int argc, char *argv[])
    {
        pile_chaine tab_chaine(5);
        chaine ch("test1");
        tab_chaine.empiler(ch);
        .............
    }
    De plus si tu veux empêcher le compilateur de construire implicitement des objets (à moins que ça soit vraiment voulu) tu peux ajouter 'explicit' devant la déclaration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class chaine
    {
          public:
                 explicit chaine(const char* _val);
    ...
    }
    J'espère que c'est pas trop touffu comme explication

    MAT.

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut réponse transtypage
    Merci laurent et MAT de votre réponse.
    1) en ce qui concerne la réponse de laurent qui me dit la chose suivante :
    on ne peut pas creer de référence non constante sur un temporaire
    , je ne suis pas d'accord. En effet, j'ai essayé le petit programme suivant qui me prouve le contraire :
    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
    #include <cstdlib>
    #include <iostream>
     
    using namespace std;
    void f(int& a);
    int main(int argc, char *argv[])
    {
        int a=0;
        cout<<"a="<<a<<endl;
        f(a);
        system("PAUSE");
        return EXIT_SUCCESS;
    }
     
     
    void f(int& a)
    {
         a=1;
         cout<<"a="<<a<<endl;
    }
    Est-ce que tu peux m'en dire plus LAURENT ? Merci.


    2) en ce qui concerne la réponse de MAT qui me dit la chose suivante :
    En fait, dans la tentative de résolution de l'appel de méthode, le compilateur essaye en plus de construire implicitement un objet 'chaine' à partir de l'argument 'const char*'.
    Par contre cet objet 'chaine' doit être 'const' car construit sur la pile au moment de l'appel.
    , j'ai une question : pour moi tous les arguments de fonction sont construit sur la pile, donc il n'y a aucune justification comme quoi
    cet objet 'chaine' doit être 'const' car construit sur la pile au moment de l'appel
    . Pour moi, même si l'argument n'est pas 'const', il est quand même construit sur la pile. Est-ce que tu peux m'en dire plus MAT ? Merci d'avance.

    3) dernière question concernant le forum: pour être sur que vous suiviez la discussion engagée, comment est-il possible de vous prévenir sur ce forum que la discussion a avancé ?

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Est-ce que tu peux m'en dire plus LAURENT ? Merci.
    Je voulais parler d'un temporaire non nommé, càd une variable construite à la volée.

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Citation Envoyé par flamant
    Pour moi, même si l'argument n'est pas 'const', il est quand même construit sur la pile.
    Tous les arguments ne peuvent pas être construits (sur la pile) à la volée (lors de l'appel). Seuls les arguments const peuvent se permettre ça.

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void f( std::string& ) {}
     
    int main( int, char*[] )
    {
      f( std::string() );
      return 0;
    }
    n'est pas valide d'après le standard du C++.

    Pour le rendre valide il faut soit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void f( const std::string& ) {}
    soit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      std::string s;
      f( s );
    Quand tu écris :
    c'est équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const std::string s;
    f( s );
    En fait je parle de la même chose que Laurent

    Citation Envoyé par flamant
    pour être sur que vous suiviez la discussion engagée, comment est-il possible de vous prévenir sur ce forum que la discussion a avancé ?
    Ca se fait tout seul lorsqu'on a activé l'option dans la configuration de son profil.

    MAT.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut réponse : (débutant : question technique sur le transtypage)
    Merci LAURENT et MAT,
    je saisis mieux ce que vous voulez dire. je considère que c'est résolu.

    Une précision concernant MAT :
    void f( std::string& ) {}

    int main( int, char*[] )
    {
    f( std::string() );
    return 0;
    }
    Dans cet exemple que tu me donnes, "std::string&" représente t-il bien une référence sur une chaine de caractère (je n'ai pas le standard C++, mais je crois que string désigne une chaine dans le standard). Et est-ce que "std::string()" représente l'appel d'une fonction (qui renverrai une référence sur une chaine de caractère) ?
    Si j'ai bien saisi "std::string()" renverrai une référence sur une chaine de caractère qui n'est pas nommée, donc "à la volée". Ceci nécessite donc qu'on déclare l'argument "const std::string&" dans f. Est-ce que j'ai bien saisi ?

    Question pour LAURENT et MAT : j'ai 2 ouvrages de C++ : 1 assez concis et 1 de 1200 pages. Je croyais que ce dernier était complet, mais je me suis apperçu qu'il manquait des choses (par exemple il n'y a rien sur les types string qui désignerait des chaines de caractère dans le standard ou il n'y a rien des explications que vous m'avez donné pour mon problème de cette discussion). Ma question est la suivante : connaissez vous un ouvrage (en français si possible) très très complet qui reprenne le standard du C++ et qui aborde le maximum des spécificités du C++ et qui soit de bonne qualité pour les explications (avec exercices corrigés si possible)?
    Merci de votre réponse. A bientôt.

  8. #8
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Citation Envoyé par flamant
    Dans cet exemple que tu me donnes, "std::string&" représente t-il bien une référence sur une chaine de caractère
    Oui.
    Citation Envoyé par flamant
    Et est-ce que "std::string()" représente l'appel d'une fonction (qui renverrai une référence sur une chaine de caractère) ?
    Non, c'est l'appel au constructeur de la classe std::string.
    Citation Envoyé par flamant
    Si j'ai bien saisi "std::string()" renverrai une référence sur une chaine de caractère qui n'est pas nommée, donc "à la volée". Ceci nécessite donc qu'on déclare l'argument "const std::string&" dans f. Est-ce que j'ai bien saisi ?
    std::string() construit une chaîne de caractères.
    Le fait d'écrire f( std::string() ) fait que cette chaîne est construite à la volée et passée directement en paramètre à f.
    C'est ce qu'il se passe (de manière implicite) lors de l'appel à empiler dans ton premier morceau de code : tu passes un const char* (le type de "test1") et le compilateur essaye de construire un 'chaine' temporaire pour le passer en paramètre, puisque c'est ce que 'empiler' accepte comme argument.

    MAT.

  9. #9
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 287
    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 287
    Par défaut
    Relativement au bouquin. Tu peux donner le nom du tien histoire qu'on le rajoute à la blacklist des bouquins à déconseiller.
    Sinon, avec une petite recherche tu trouveras vite le bouquin de Stroustrup comme ouvrage de référence général sur le C++ -- il y a d'autres ouvrages de référence plus pointus, et quantité d'autres types de bouquins excellents.
    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...

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut réponse (débutant : question technique sur le transtypage)
    Merci LAURENT, MAT et LUC de vos explications et interventions.
    Xavier

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Question technique sur l'indemité de stage.
    Par Toncelan dans le forum Paie
    Réponses: 9
    Dernier message: 24/11/2008, 16h24
  2. [Débutant] Question simple sur les checkbox
    Par Mil17 dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 01/08/2007, 15h05
  3. Question technique sur les listes déroulantes
    Par kenny49 dans le forum Langage
    Réponses: 3
    Dernier message: 18/04/2007, 10h41
  4. Question technique sur Source Engine
    Par Reyem dans le forum Moteurs 3D
    Réponses: 15
    Dernier message: 20/10/2006, 16h00
  5. Question techniques sur les extents
    Par lecharcutierdelinux dans le forum Oracle
    Réponses: 16
    Dernier message: 24/08/2006, 09h01

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