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 :

Friend name injection


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut Friend name injection
    Salut,

    Voilà, je lis actuellement C++ template: The complete guide (très bon livre soit dit en passant) et dans cet ouvrage il est question du problème de l'injection des noms lors d'une déclaration d'amitié dans le namespace qui englobe la classe dans laquelle a lieu cette déclaration. Pour voir si j'ai bien compris le problème j'ai donc fait un petit programme qui illustre ce thème :
    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
    #include <iostream>
     
    #ifdef _WIN32
    #define __PRETTY_FUNCTION__ __FUNCTION__
    #endif
     
    void print();
     
    namespace A
    {
      class Test
      {
        friend void print(); //Injection de print dans A
        friend void print2(const Test &); //Injection de print2 dans A
      };
     
      void callPrint()
      {
        print(); //Normalement ici A::print n'est pas visible c'est donc ::print qui est appelée
        print2(Test()); //Ici A::print2 est visible grâce à l'ADL c'est donc A::print2 qui est appelée et l'édition de lien doit échouer puisque A::print2 n'est pas définie
      }
    }
     
    void print()
    {
      std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
     
    void print2(const A::Test &)
    {
      std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
     
    int main(void)
    {
      A::callPrint();
      return 0;
    }
    Le problème c'est qu'avec le compilateur de Visual C++ 2005 j'ai un message à l'édition de lien qui m'indique que A::print n'est pas définie. Ma question est donc : est-ce que je n'ai rien compris ou bien est-ce un "bug" du compilateur de Windows ?

    D'avance merci pour vos réponses

  2. #2
    Membre éprouvé
    Inscrit en
    Avril 2008
    Messages
    155
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 155
    Par défaut
    Lorsque le compilo fait son boulot,
    au niveau de call_print il tombe sur une fonction non définie

    ==>
    a mon avis ca devrais marcher si tu défini comme ca:


    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
     namespace A
    {
      class Test
      {
        friend void print(); //Injection de print dans A
        friend void print2(const Test &); //Injection de print2 dans A
      };
     
      void print()
       {
         std::cout << __PRETTY_FUNCTION__ << std::endl;
       }
     
       void print2(const A::Test &)
       {
         std::cout << __PRETTY_FUNCTION__ << std::endl;
       } 
     
     
      void callPrint()
      {
        print(); //Normalement ici A::print n'est pas visible c'est donc ::print qui est appelée
        print2(Test()); //Ici A::print2 est visible grâce à l'ADL c'est donc A::print2 qui est appelée et l'édition de lien doit échouer puisque A::print2 n'est pas définie
      }
    }

    balises [code] ajoutées par r0d

  3. #3
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut
    Citation Envoyé par loicounet Voir le message
    Lorsque le compilo fait son boulot,
    au niveau de call_print il tombe sur une fonction non définie

    ==>
    a mon avis ca devrais marcher si tu défini comme ca:


    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
     namespace A
    {
      class Test
      {
        friend void print(); //Injection de print dans A
        friend void print2(const Test &); //Injection de print2 dans A
      };
     
      void print()
       {
         std::cout << __PRETTY_FUNCTION__ << std::endl;
       }
     
       void print2(const A::Test &)
       {
         std::cout << __PRETTY_FUNCTION__ << std::endl;
       } 
     
     
      void callPrint()
      {
        print(); //Normalement ici A::print n'est pas visible c'est donc ::print qui est appelée
        print2(Test()); //Ici A::print2 est visible grâce à l'ADL c'est donc A::print2 qui est appelée et l'édition de lien doit échouer puisque A::print2 n'est pas définie
      }
    }
    Ben non justement, si j'ai bien compris le truc ton code ne doit pas compiler puisque la fonction A::print injecté par la déclaration friend n'est pas visible pour callPrint. Mais bizarrement ton code compile parfaitement avec Visual C++ 2005. Je réitère donc ma question : est ce moi qui suis à côté de la plaque ou bien le compilateur Windows ?

  4. #4
    Membre éprouvé
    Inscrit en
    Avril 2008
    Messages
    155
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 155
    Par défaut
    je viens de lire dans mon bouquin:

    Une classe amie doit préalablement etre declaree dans la portee dans laquelle elle se trouve incluse, ou etre definie dans la portee hors classe de premier niveau englobant la classe qui la declare comme amie. par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class X{/*...*/}  //amie de Y
     
    namespace N
    {
      class Y{
           friend class X;
           friend class Z;
           friend class AE;   
                };
       class Z{...}  //amie de Y
    }
     
    class AE{...}   //pas amie
    ===>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <iostream>
     
    #ifdef _WIN32
    #define __PRETTY_FUNCTION__ __FUNCTION__
    #endif
     
    void print();
    void print2(const A::Test &);  //il manquait celle la?
     
    namespace A
    {
      ...
    bon apres faut se poser la question si call_print a bien acces a print()
    :
    ya pas de notation du style possible?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     void callPrint()
      {
        Test::print(); 
        Test::print2(Test()); 
      }

  5. #5
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    Salut,

    si tu déclarais toutes tes fonctions avant de les définir, tu n'aurais aucun problème

    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
    #include <iostream>
     
    #ifdef _WIN32
    #define __PRETTY_FUNCTION__ __FUNCTION__
    #endif
     
    namespace A
    {
        class Test;
    }
     
    void print();
    void print2(const A::Test &);
     
    namespace A
    {
      class Test
      {
        friend void ::print(); //Injection de print dans A
        friend void ::print2(const Test &); //Injection de print2 dans A
      };
     
      void callPrint()
      {
        print(); //Normalement ici A::print n'est pas visible c'est donc ::print qui est appelée
        print2(Test()); //Ici A::print2 est visible grâce à l'ADL c'est donc A::print2 qui est appelée et l'édition de lien doit échouer puisque A::print2 n'est pas définie
      }
    }
     
    void print()
    {
      std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
     
    void print2(const A::Test &)
    {
      std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
     
    int main(void)
    {
      A::callPrint();
      return 0;
    }
    Les '::' sont pour dire que print et print2 ne font pas partie du namespace A, mais du namespace global.

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut
    Je crois que je ne me suis pas bien fait comprendre. Le code ci-dessous :
    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
    #include <iostream>
     
    #ifdef _WIN32
    #define __PRETTY_FUNCTION__ __FUNCTION__
    #endif
     
    void print();
     
    namespace A
    {
      class Test
      {
        friend void print(); //Injection de print dans A
      };
     
      void callPrint()
      {
        print(); //Normalement ici A::print n'est pas visible c'est donc ::print qui est appelée
      }
    }
     
    void print()
    {
      std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
     
    int main(void)
    {
      A::callPrint();
      return 0;
    }
    devrait, si j'ai bien compris le principe du friend name injection, compilé. Or avec Visual C++ 2005 ce n'est pas le cas. Le linker se plaint de ne pas trouver la définition de A::print. (Je viens de tester ce code avec gcc 4.3.0 il compile parfaitement mais avec d'autre compilateur ça ne fonctionne pas). J'aimerais donc savoir, si possible, qui a tort et qui a raison.

Discussions similaires

  1. Problème avec les friendly name
    Par samus535 dans le forum SSAS
    Réponses: 1
    Dernier message: 11/11/2008, 16h33
  2. [EJB] [JBOSS][javax.naming.NameNotFoundException]
    Par hamed dans le forum Java EE
    Réponses: 5
    Dernier message: 18/12/2003, 18h00
  3. [XSL] insérer une balise <a name>
    Par guibong dans le forum XMLRAD
    Réponses: 2
    Dernier message: 01/08/2003, 15h04
  4. TXMLModule.create - name = resource not found
    Par pram dans le forum XMLRAD
    Réponses: 2
    Dernier message: 04/03/2003, 10h54
  5. naming service
    Par manuel dans le forum CORBA
    Réponses: 6
    Dernier message: 09/12/2002, 17h43

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