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

Langage C++ Discussion :

namespace et extern (multiple definition)


Sujet :

Langage C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut namespace et extern (multiple definition)
    Bonjour à tous,

    Je rencontre un sérieux problème en reprenant le C++ dans mon utilisation des namespace. J'essaie de faire un espace spécial pour les globales, d'où son nom, qui contient une variable et quelques fonctions. Le problème c'est que j'obtiens des erreurs pour le moins étrange !

    D'un côté si j'utilise un extern pour la variable Log, le compilateur m'indique qu'il ne trouve pas de "Globals::Log" (erreur #1) ! Et si je l'enlève il m'indique je le définis plusieurs fois (dans main.cpp !!! erreur #2). En faisant avec le extern un make clean all (#1ère erreur) puis en l'enlevant et en refaisant un make ça compile et tourne.

    main.cpp (l'header include globals.hpp)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef MAIN_C
    #	define MAIN_C
     
    #include "main.hpp"
     
    int main(int argc, char *argv[]) {
    	Globals::Init();
    	Globals::Log(LOGGER_TYPE_DEBUG, LOGGER_CAT_SYSTEM, false, "Program is over");
    }
    #endif
    globals.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #ifndef GLOBALS_H
    #	define GLOBALS_H
    
    #include <stdlib.h>
    #include <stdarg.h>
    #include "logger.hpp"
    
    namespace Globals {
    	extern Logger log; /* extern ou non, tel est la QUESTION ! */
    	
    	void Init();
    	void Log(unsigned int type, unsigned int cat, bool fatal, char *message, ...);
    }
    #endif
    globals.cpp
    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
    #ifndef GLOBALS_C
    #	define GLOBALS_C
     
    #include "globals.hpp"
     
    void Globals::Init() {
    	loggerInit(&log);
    	log.toConsole = 1;
    }
     
    void Globals::Log(unsigned int type, unsigned int cat, bool fatal, char *message, ...) {
    	va_list args;
    	va_start(args, message);
    	loggerPush(&log, type, cat, message, args);
    	va_end(args);
    	if (fatal)
    		exit(EXIT_FAILURE);
    }
    #endif
    erreur #1:
    build/globals.o: In function `Globals::Init()':
    src/globals.cpp:7: undefined reference to `Globals::log'
    src/globals.cpp:8: undefined reference to `Globals::log'
    build/globals.o: In function `Globals::Log(unsigned int, unsigned int, bool, char*, ...)':
    src/globals.cpp:15: undefined reference to `Globals::log'
    collect2: ld a retourné 1 code d'état d'exécution
    make: *** [main] Erreur 1
    erreur #2:
    build/globals.o:src/globals.cpp:6: multiple definition of `Globals::log'
    build/main.o:src/main.cpp:11: first defined here // je ne fais que l'utiliser pourtant !
    build/socketserver.o: In function `SocketServer':
    src/socketserver.cpp:6: multiple definition of `Globals::log' // pareil !
    build/main.o:src/main.cpp:11: first defined here
    build/socketserverlistener.o: In function `SocketServerListener':
    src/socketserverlistener.cpp:6: multiple definition of `Globals::log' // pareil
    build/main.o:src/main.cpp:11: first defined here
    build/server.o: In function `Server':
    src/server.cpp:6: multiple definition of `Globals::log'
    build/main.o:src/main.cpp:11: first defined here
    collect2: ld a retourné 1 code d'état d'exécution
    make: *** [main] Erreur 1
    Quelqu'un peut-il m'expliquer où est-ce que ça cloche svp ? Peut-être que le Makefile pose problème donc demandez moi de le poster si nécessaire.

  2. #2
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2006
    Messages
    153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 153
    Par défaut
    Bonjour

    As tu besoin que ta variable Logger log; soit visible de l'exterieur ? Je dirais que non. La solution la plus simple est donc la suivante :

    globals.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #ifndef GLOBALS_H
    #	define GLOBALS_H
     
    #include <stdlib.h>
    #include <stdarg.h>
     
    namespace Globals {
    	void Init();
    	void Log(unsigned int type, unsigned int cat, bool fatal, char *message, ...);
    }
    #endif
    globals.cpp
    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
    #include "globals.hpp"
    #include "logger.hpp"
     
    static Logger log;
     
    void Globals::Init() {
    	loggerInit(&log);
    	log.toConsole = 1;
    }
     
    void Globals::Log(unsigned int type, unsigned int cat, bool fatal, char *message, ...) {
    	va_list args;
    	va_start(args, message);
    	loggerPush(&log, type, cat, message, args);
    	va_end(args);
    	if (fatal)
    		exit(EXIT_FAILURE);
    }
    #endif
    Un autre solution serait de définir ta variable log comme variable static membre d'une structure :

    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
    //globals.hpp
    ...
    struct Global {
       static Logger log;
    };
    ...
     
    //global.cpp
    Logger Global::log; // définition de la variable log (unique instance)
     
     
    void Globals::Init() {
    	loggerInit(&Global::log);
    	Global::log.toConsole = 1;
    }

  3. #3
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Si tu la déclares extern dans le .hpp, elle est seulement déclarée, pas définie.

    Il faut donc que tu rajoutes sa définition dans le .cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Logger.h
    namespace Globals
    {
         extern Logger Log;
    }
     
    // Logger.cpp
    namespace Globals
    {
         Logger Log;
    }

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    152
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Août 2004
    Messages : 152
    Par défaut
    Bonjour à vous deux,

    merci de vous être penché sur mon problème! Vos solutions fonctionnent toutes parfaitement et je vous en remercie. Je préfère utiliser la solution de white_tentacle car elle me permettra de garder mes variables globales dans un namespace (un struct peut aussi être considérer comme un singleton si on veut cependant le namespace est sûrement plus propre en C++). jfouche tu as bien raison, je n'ai pas besoin que Logger log soit visible de l'extérieur, je n'avais même pas remarquer que je pouvais l'utiliser ainsi.

    Si tu la déclares extern dans le .hpp, elle est seulement déclarée, pas définie.
    Effectivement, n'ayant quasiment jamais utiliser extern je vois que j'ai oublié quelque chose de vital.

    Merci à vous deux pour vos réponses complètes et rapides ! Pas de rancune alors jfouche

  5. #5
    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
    Par défaut
    Citation Envoyé par jamesb Voir le message
    un struct peut aussi être considérer comme un singleton si on veut cependant le namespace est sûrement plus propre en C++
    namespace ou singleton, c'est la même chose : une variable globale.
    La réponse de jfouche permet de limiter la visibilité de cette variable à un seul fichier.

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 19/09/2006, 15h42
  2. multiple definition of operator<<...
    Par kleenex dans le forum C++
    Réponses: 3
    Dernier message: 05/05/2006, 02h56
  3. [Oracle 8] Jointure externe multiple et valeurs nulles !!!
    Par nsonnier dans le forum Langage SQL
    Réponses: 2
    Dernier message: 20/03/2006, 22h22
  4. [LG]Interfaces et multiples définitions
    Par fatt dans le forum Langage
    Réponses: 2
    Dernier message: 15/04/2004, 22h41
  5. multiple definition
    Par scorbo dans le forum C
    Réponses: 5
    Dernier message: 10/09/2003, 13h16

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