Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3509 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Redefinition de namespace

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Redefinition de namespace

n°1619860
nathan_g
Posté le 05-10-2007 à 16:56:38  profilanswer
 

Bonjour,  
 
Je rencontre un comportement curieux à la compilation de plusieurs fichiers.
 
J'ai une fichier Article.H :
 

Code :
  1. class Article
  2. {
  3. public:
  4.   double prix;
  5.   double tva();
  6. };


 
Un fichier Article.C :
 

Code :
  1. #include "Article.H"
  2. double Article::tva()
  3. {
  4.   return (0.196*prix);
  5. }


 
et un fichier main.C :
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. #include "Article.H"
  4. int main()
  5. {
  6.   Article pomme;
  7.   pomme.prix = 5;
  8.   cout << pomme.tva() << endl;
  9. }


 
Quand je compile séparément les deux fichiers Article.C et main.C puis que j'en réalise l'édition de liens, cela fonctionne parfaitement malgré l'apparition du code de Article.H à deux occasions dans l'executable final (Au début de Article.C et de main.C ).
 
Par contre, si je rajoute un namespace dans Article.H en l'écrivant ainsi :
 

Code :
  1. class Article
  2. {
  3. public:
  4.   double prix;
  5.   double tva();
  6. };
  7. namespace Fruit
  8. {
  9.   double poids;
  10. }


 
Je trouve une erreur de compilation :
 

Code :
  1. main.o(.bss+0x0): multiple definition of `Fruit::poids'
  2. Article.o(.bss+0x0): first defined here
  3. collect2: ld returned 1 exit status


 
Pourtant si la première version de Article avec une redéfiniton des déclarations de Article.H est acceptée à la compilation, la seconde version devrait fonctionner, non ?
 
Quelqu'un pourrait-il m'indiquer ou est le problème et la raison pour laquelle la première version est compilable et pas la seconde ?
Quelle serait la solution à adopter ?
 
D'avance merci de votre aide,

mood
Publicité
Posté le 05-10-2007 à 16:56:38  profilanswer
 

n°1619899
tuxce
Posté le 05-10-2007 à 17:43:08  profilanswer
 

salut,
il faudrait ajouter:

Code :
  1. #ifndef ARTICLE_H
  2. #define ARTICLE_H
  3. /* ton code de article.h
  4. */
  5. #endif
 


je crois que la différence de comportement vient du fait que poids est alloué en mémoire, alors qu'avant, ce n'était que des définitions.

 

EDIT: trop vite sans faire attention, je le corrige quand meme.


Message édité par tuxce le 05-10-2007 à 17:55:18
n°1619901
nathan_g
Posté le 05-10-2007 à 17:49:26  profilanswer
 

La commande est :
 

Code :
  1. #ifndef ARTICLE_H


 
et non :
 

Code :
  1. #ifundef ARTICLE_H


 
J'ai déja indiqué ces lignes sans que cela change quelquechose. Je ne les avais pas précisées pour alléger ma question.
Le problème n'est pas résolu avec cette modification.
 
Est-ce que vous connaitriez une solution ?
 
Cordialement,

n°1620017
Taz
bisounours-codeur
Posté le 06-10-2007 à 00:29:40  profilanswer
 

définition != déclaration

n°1620020
tuxce
Posté le 06-10-2007 à 01:40:08  profilanswer
 

ce que tu peux faire, c'est déclarer les eventuelles fonctions/classes dans le .h, et les variables, dans le .cc (c'est du c++ ;))

Code :
  1. class Article
  2. {
  3.         public:
  4.                 double prix;
  5.                 double tva();
  6. };
  7. namespace Fruit{};


Code :
  1. #include "article.h"
  2. namespace Fruit
  3. {
  4. double poids=0;
  5. };
  6. double Article::tva()
  7. {
  8. return (0.196*prix);
  9. }


Code :
  1. #include <iostream>
  2. #include "article.h"
  3. using namespace std;
  4. extern double Fruit::poids;
  5. int main()
  6. {
  7. Article pomme;
  8. pomme.prix = 5;
  9. cout << pomme.tva() << endl;
  10. cout << poids << endl;
  11. }


 
mais par contre, je suis pas sur que ca soit indispensable de déclarer une variable global de cette facon!

n°1620392
nathan_g
Posté le 08-10-2007 à 09:40:11  profilanswer
 

Merci de ces réponses.
J'aimerais comprendre plus précisément quel était mon erreur.
 
Est-ce qu'il y avait une double déclaration de la variable poids du namespace et que cela posait problème ?
Pourtant, quand je déclare la variable prix de la classe Article, elle apparait deux fois à la compilation (dans Article.o et main.o), sans que cela pose problème à l'édition de liens.
 
Pourquoi ce comportement différent ?

n°1620468
tuxce
Posté le 08-10-2007 à 12:01:00  profilanswer
 

la variable prix n'est pas allouée, alors que poids si.
aucune instance de Article n'est déclaré dans le article.h.

n°1620499
nathan_g
Posté le 08-10-2007 à 13:22:33  profilanswer
 

Pour mieux comprendre, ce que tu dis, l'écriture  
 

Code :
  1. class Article
  2. {
  3. public:
  4. double prix;
  5. double tva();
  6. };


 
ne correspondrait pas à une allocation de poids
 
alors que :
 

Code :
  1. namespace Fruit
  2. {
  3. double poids;
  4. }


 
correspondrait à allouer la variable poids ?
 
Est-ce bien cela que tu indiques ?
 
Pourquoi cette différence de comportement ?

n°1620506
tuxce
Posté le 08-10-2007 à 13:36:05  profilanswer
 

Je suis pas expert, mais je sais que:

Code :
  1. #include <iostream>
  2. class A
  3. {
  4.   public:
  5.     int x=0;
  6. };
  7. int main ()
  8. {
  9.   std::cout << A::x;
  10.   return 0;
  11. }


provoque une erreur car il n'y a aucune instance de A, ce n'est que la définition de la classe.
 
alors que

Code :
  1. #include <iostream>
  2. namespace A
  3. {
  4.   int x=0;
  5. };
  6. int main ()
  7. {
  8.   std::cout << A::x;
  9.   return 0;
  10. }


fonctionne car x est alloué en mémoire, le namespace ne fait que définir un espace pour les déclarations.

n°1620548
nathan_g
Posté le 08-10-2007 à 14:32:57  profilanswer
 

Bonjour,
 
Merci de ces différentes précisions.
 
J'ai essayé le code donné plus haut avec les trois fichiers mais cela ne semble pas accepter. D'une part, je ne parviens à définir le namespace en deux parties (d'une part dans Article.H, d'autre part dans Article.cpp. Ensuite, en déplaçant les lignes de code, je conserve un problème sur la non-déclaration ou des déclarations multiples de variables.

mood
Publicité
Posté le 08-10-2007 à 14:32:57  profilanswer
 

n°1620560
Taz
bisounours-codeur
Posté le 08-10-2007 à 14:50:16  profilanswer
 

tuxce a écrit :

Je suis pas expert, mais je sais que:

Code :
  1. #include <iostream>
  2. class A
  3. {
  4.   public:
  5.     int x=0;


Illégal.


 
J'aimerais qu'on arrête de traiter le même problème dans 36 sujets. Déclaration != définition. Quelque soit votre membre statique, variable globale dans un namespace ou pas, il vous FAUT:
- .h qui contient la déclaration
- .cpp qui contient la définition et initialisation

n°1620577
nathan_g
Posté le 08-10-2007 à 15:13:24  profilanswer
 

Je veux bien essayer de revenir à ce sujet mais, dans ce cas, peut-tu donner un exemple simple d'utilisation d'une variable dans un namespace (et non pas d'une méthode). J'ai l'impression qu'il me faut passer par la redefinition d'une classe dans mon namespace pour cela.

n°1620585
Taz
bisounours-codeur
Posté le 08-10-2007 à 15:25:18  profilanswer
 

redéfinition  = illégal

 

a.h
namespace A { extern int x; }

 

a.cpp
namespace A { int x = 42; }

 

et voilà tu peux utiliser A::x partout.


Message édité par Taz le 08-10-2007 à 16:25:31
n°1620601
tuxce
Posté le 08-10-2007 à 15:43:09  profilanswer
 

sauf si a.h est inclus dans 2 .cpp différents.
 

nathan_g a écrit :

J'ai essayé le code donné plus haut avec les trois fichiers mais cela ne semble pas accepter. D'une part, je ne parviens à définir le namespace en deux parties (d'une part dans Article.H, d'autre part dans Article.cpp. Ensuite, en déplaçant les lignes de code, je conserve un problème sur la non-déclaration ou des déclarations multiples de variables.


tu peux poster la sortie?
chez moi, ca fonctionne (avec g++ -Wall: pas d'erreur)

n°1620611
nathan_g
Posté le 08-10-2007 à 15:52:50  profilanswer
 

Tuxce : merci de ce détail (sauf...) qui doit changer pas mal de chose.
 
En l'occurence, de manière simplifiée, mon code qui ne fonctionne pas est :
 
Fichier Article.H
 

Code :
  1. #ifndef  _ARTICLE_
  2. #define  _ARTICLE_
  3. namespace Article
  4. {
  5.   double poids;
  6. };
  7. #endif


 
Fichier Article.C:
 

Code :
  1. #include "Article.H"
  2. namespace Article
  3. {
  4.   double poids = 0.3;
  5. };


 
Fichier main.C
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. #include "Article.H"
  4. using namespace Article;
  5. int main()
  6. {
  7.   cout << Article::poids << endl;
  8.   return (1);
  9. };


 
La compilation ne fonctionne pas et me sort le message :
 

Code :
  1. Article.C:5: error: redefinition of `double Article::poids'
  2. Article.H:6: error: `double Article::poids' previously declared here


 
Comment donner à tout cela une écriture correcte ?
J'ai du rater quelque chose mais je ne vois pas comment donner une écriture correcte à ce code.

n°1620615
tuxce
Posté le 08-10-2007 à 16:00:20  profilanswer
 

ca d'accord...
mais tu as essayé le code avec extern, je t'avais remis les 3 fichiers:
http://forum.hardware.fr/forum2.ph [...] 0#t1620020


Message édité par tuxce le 08-10-2007 à 16:01:33
n°1620621
Taz
bisounours-codeur
Posté le 08-10-2007 à 16:23:57  profilanswer
 

putain je suis fatigué moi... désolé

n°1620629
tuxce
Posté le 08-10-2007 à 16:43:06  profilanswer
 

Taz a écrit :

putain je suis fatigué moi... désolé


t'aurais pu rajouter à coté du "fatigué" comme quoi tu as édité le post d'avant en ajoutant le extern ;)
en gros, ca revient à ce que j'ai posté avant!


Message édité par tuxce le 08-10-2007 à 16:43:42
n°1620633
nathan_g
Posté le 08-10-2007 à 16:49:41  profilanswer
 

Merci Tuxce de ton implication dans mon problème.
 
A moins que j'ai mal compris, j'ai modifié le précédent fichier main.C afin d'y inclure le " extern " ce qui donne le fichier main.C suivant , les deux autres n'étant pas modifiés  :
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. #include "Article.H"
  4. using namespace Article;
  5. extern double Article::poids;
  6. int main()
  7. {
  8.   cout << Article::poids << endl;
  9.   return (1);
  10. };


 
Malheureusement, cela ne résouds en rien mon problème car le message d'erreur n'est pas modifié. Désolé !

n°1620647
tuxce
Posté le 08-10-2007 à 17:20:14  profilanswer
 

il faut modifier les autres aussi:
article.h:

Code :
  1. namespace Fruit {};


article.c:

Code :
  1. namespace Fruit
  2. {
  3.   double poids=0;
  4. };
 


Message édité par tuxce le 08-10-2007 à 18:23:11
n°1620666
nathan_g
Posté le 08-10-2007 à 17:33:59  profilanswer
 

Bon, sans doute que j'ai un peu de mal ;)
Maintenant, le code est :
 
Article.H
 

Code :
  1. namespace Article {};


 
Article.C :
 

Code :
  1. #include "Article.H"
  2. namespace Article
  3. {
  4.   double poids = 0.3;
  5. };


 
et main.C :
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. #include "Article.H"
  4. using namespace Article;
  5. extern double Article::poids;
  6. int main()
  7. {
  8.   cout << Article::poids << endl;
  9.   return (1);
  10. };


 
Malheureusement, ca ne compiletoujours pas. Le message est maintenant :
 

Code :
  1. main.C:9: error: `Article::poids' should have been declared inside `Artcle'
  2. main.C: In function `int main()':
  3. main.C:13: error: `poids' is not a member of `Article'
  4. /usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../crt1.o(.text+0x18):In function `_start':
  5. ../sysdeps/i386/elf/start.S:98: undefined reference to `main'
  6. collect2: ld returned 1 exit status


 
Qu'est ce que j'ai raté ?
Ou est-le problème dans cette nouvelle écriture ?

n°1620700
tuxce
Posté le 08-10-2007 à 18:33:10  profilanswer
 

faudra que tu m'expliques pourquoi tu n'as pas pris tel quel l'exemple que je t'ai donnée!!!
 
pour ton programme, il faut modifier:

Code :
  1. cout << Article::poids << endl;


par

Code :
  1. cout << poids << endl;

n°1620704
nathan_g
Posté le 08-10-2007 à 18:37:14  profilanswer
 

Bonsoir,
 
Merci de cette nouvelle réponse, mais ce que tu proposes ne change absolument rien.
Le message d'erreur reste identique !
 
Peut-tu me confirmer que, de ton coté, la compilation de ces trois fichiers est acceptée et donne un executable fonctionnant normalement ?

n°1620709
Taz
bisounours-codeur
Posté le 08-10-2007 à 18:46:08  profilanswer
 

Voir mon exemple corrigé
 

Code :
  1. $ cat a.cc
  2. #include "a.hh"
  3. namespace A { int x = 42; }
  4. $ cat a.hh
  5. namespace A { extern int x; }
  6. $ cat main.cc
  7. #include "a.hh"
  8. int main() { return A::x; }
  9. $ g++ -Wall main.cc a.cc
  10. $ ./a.out; echo $?
  11. 42

n°1620712
nathan_g
Posté le 08-10-2007 à 18:51:06  profilanswer
 

OK !!!!!!
 
Merci beaucoup Taz de cet exemple qui fonctionne parfaitement  :) .
 
Il ne me reste plus qu'à analyser tout cela pour comprendre mes problèmes  ;) .
 
Merci également Tuxce du temps passé.
 
Je dormirais mieux ce soir.

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Redefinition de namespace

 

Sujets relatifs
Question à la con : parcourir un namespace...the type or namespace 'Office' does not exists in 'Microsoft'
Problème de namespaceTemplate, namespace, autre ?
[RESOLU] VBS : Problème de redéfinition de variableProblème de Namespace (EXSLT)
[C++] include et redefinition de typeRédéfinition de sujet
redefinition incomprehensible :'(Probleme classe heritant vector : redéfinition erase()
Plus de sujets relatifs à : Redefinition de namespace


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)