[C++] constructeur et variable statique
Résolu/Fermé
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
-
9 févr. 2010 à 08:44
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 - 17 févr. 2010 à 13:03
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 - 17 févr. 2010 à 13:03
A voir également:
- [C++] constructeur et variable statique
- Adresse mac constructeur - Guide
- Variable drapeau - Forum Python
- Formule excel plage de données variable ✓ - Forum Excel
- Vba msgbox variable ✓ - Forum VB / VBA
- Impossible de créer le fichier de travail. vérifiez la variable d'environnement temp ✓ - Forum Windows 10
15 réponses
Bonjour,
Tu as une classe Mots contenant une liste de mots.
Mais la liste ne contiendra toujours qu'UN SEUL mot, car seul le constructeur y ajoute quelque-chose. Çà ne sert pas à grand chose...
Pour créer ta liste de mots, comment fais-tu ?
T'as pas de méthode ajouterMot pour ajouter un mot dans la liste ?
De plus, que signifie "avant le main je rempli la variable mots" ? AVANT le main ? Comment fais tu ?
Bref, soit je n'ai pas compris grand chose à ta question,
Ou soit tu n'a pas compris grand chose à la programmation objet.
En espèrant t'avoir aidé...
Tu as une classe Mots contenant une liste de mots.
Mais la liste ne contiendra toujours qu'UN SEUL mot, car seul le constructeur y ajoute quelque-chose. Çà ne sert pas à grand chose...
Pour créer ta liste de mots, comment fais-tu ?
T'as pas de méthode ajouterMot pour ajouter un mot dans la liste ?
De plus, que signifie "avant le main je rempli la variable mots" ? AVANT le main ? Comment fais tu ?
Bref, soit je n'ai pas compris grand chose à ta question,
Ou soit tu n'a pas compris grand chose à la programmation objet.
En espèrant t'avoir aidé...
mamiemando
Messages postés
33093
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
4 mai 2024
7 752
9 févr. 2010 à 14:12
9 févr. 2010 à 14:12
@Char Sniper: Pour commencer j'utiliserais un std::set<std::string> pour stocker les mots, ce qui évitera les problèmes liés aux doublons, permettra un accès en O(log(n)) (au lieu de O(n) pour vérifier la présence ou non d'un mot dans la "liste").
@swed : non sa "liste" contiendra bien plusieurs mots, c'est tout l'intérêt d'un membre statique : celui-ci est commun à toutes les instances de la classe "mots".
@Char sniper : peux-tu nous donner un exemple de code minimal ? Pour accéder à ton membre statique, il faut soit un accesseur (static) soit y accéder en tant que tel. Je ne peux pas tester dans l'immédiat mais ça ressemble à ça :
Ceci dit je ferais plus simplement :
Bonne chance
@swed : non sa "liste" contiendra bien plusieurs mots, c'est tout l'intérêt d'un membre statique : celui-ci est commun à toutes les instances de la classe "mots".
@Char sniper : peux-tu nous donner un exemple de code minimal ? Pour accéder à ton membre statique, il faut soit un accesseur (static) soit y accéder en tant que tel. Je ne peux pas tester dans l'immédiat mais ça ressemble à ça :
#include <set> #include <string> #include <iostream> class mots_t{ public: typedef std::set<std::string> list_t; protected: static list_t list; public: mots(const std::string & mot){ list.insert(mot); } inline static const list_t & get_list() const{ return list; } }; int main(){ mots_t mots1("pouet"); mots_t mots2("plop"); // Accès à mots_t::list const mots_t::list_t & list = mots_t::get_list(); // Afficher les mots mots_t::list_t::const_iterator mots_it (list.begin()), mots_end(list.end()); for(;mots_it!=mots_end;++mots_it) std::cout << *mots_it << std::endl; return 0; }
Ceci dit je ferais plus simplement :
#include <set> #include <string> #include <iostream> typedef std::set<std::string> mots_t; /* // ou encore : class mots_t : public std::set<std::string> { //... }; */ int main(){ mots_t.insert("plop"); mots_t.insert("pouet"); // Afficher les mots mots_t::const_iterator mots_it (mots.begin()), mots_end(mots.end()); for(;mots_it!=mots_end;++mots_it) std::cout << *mots_it << std::endl; return 0; }
Bonne chance
loupius
Messages postés
697
Date d'inscription
dimanche 1 novembre 2009
Statut
Membre
Dernière intervention
31 décembre 2017
148
9 févr. 2010 à 14:38
9 févr. 2010 à 14:38
#include <string> #include <vector> #include <cstdlib> #include <iostream> class Mots { public: static std::vector<std::string> liste; Mots(std::string a) { liste.push_back(a); } }; std::vector<std::string> Mots::liste; void unDePlus(std::string str) { Mots mot(str); } int main(int argc, char *argv[]) { unDePlus("table"); unDePlus("chaise"); unDePlus("fauteuil"); for (unsigned int i=0; i<Mots::liste.size(); i++) std::cout << Mots::liste[i] << std::endl; return EXIT_SUCCESS; }Cette réponse te convient-elle ?
Bonne continuation.
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 297
9 févr. 2010 à 14:47
9 févr. 2010 à 14:47
Salut.
Merci pour ton intervention mamiemando. Le set, ça peut être pas mal, mais la rapidité, je m'en fiche un peu. Je regarderai plus en détail ce que tu proposes.
Voici un code minimal qui présentera le problème : (c'est crade, mais c'est juste du test)
main.cpp :
et un fichier machin.cpp :
le problème semble venir de la STL, car après multiple essai, je me suis orienté vers une liste chainé qui fonctionne (mais autrement plus dur à mettre en oeuvre). Dans tout les cas, j'aimerai bien comprendre ce qui se passe.
Dans ce code minimal, seul a et b sont pris en compte dans la liste.
Je ne peux pas mettre les variables c et d dans la fonction lisdf(), car je ne suis pas sur que cette fonction sera appelé, mais j'ai quand même besoin de récupérer la donnée.
Merci pour ton intervention mamiemando. Le set, ça peut être pas mal, mais la rapidité, je m'en fiche un peu. Je regarderai plus en détail ce que tu proposes.
Voici un code minimal qui présentera le problème : (c'est crade, mais c'est juste du test)
main.cpp :
#include <vector> #include <string> #include <iostream> std::vector<char*>l; struct A { A(char *a){l.push_back(a);std::cout<<a<<" constructeur\n";} }; A a("essai"); A b("essa2i"); int main() { std::cout<<l.size()<<"\n";// devrai rendre 4 return 0; }
et un fichier machin.cpp :
#include <vector> #include <iostream> extern std::vector<char*> l; struct A{A(char* A);}; A c("dkjf"); A d("flgkfd"); void lisdf() { return; }
le problème semble venir de la STL, car après multiple essai, je me suis orienté vers une liste chainé qui fonctionne (mais autrement plus dur à mettre en oeuvre). Dans tout les cas, j'aimerai bien comprendre ce qui se passe.
Dans ce code minimal, seul a et b sont pris en compte dans la liste.
Je ne peux pas mettre les variables c et d dans la fonction lisdf(), car je ne suis pas sur que cette fonction sera appelé, mais j'ai quand même besoin de récupérer la donnée.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
mamiemando
Messages postés
33093
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
4 mai 2024
7 752
10 févr. 2010 à 02:26
10 févr. 2010 à 02:26
Le set, ça peut être pas mal, mais la rapidité, je m'en fiche un peu
Ce n'est pas qu'un problème de rapidité, dans ton code tu peux insérer le même mot en plusieurs exemplaires,
devrait rendre 4
Non c'est normal que ça retourne 2,
Le problème semble venir de la STL
Un peu de sérieux :-),
Je me suis orienté vers une liste chainé qui fonctionne (mais autrement plus dur à mettre en oeuvre)
Les classes std::list et std::vector ont toutes deux une méthode push_back, je ne vois pas la différence.
Dans ce code minimal, seul a et b sont pris en compte dans la liste.
Je ne peux pas mettre les variables c et d dans la fonction lisdf(), car je ne suis pas sur que cette fonction sera appelé, mais j'ai quand même besoin de récupérer la donnée.
Pas compris.
Voici le code que j'ai posté corrigé (je n'avais pas de quoi tester la dernière fois) :
et :
Bonne chance
Ce n'est pas qu'un problème de rapidité, dans ton code tu peux insérer le même mot en plusieurs exemplaires,
devrait rendre 4
Non c'est normal que ça retourne 2,
Le problème semble venir de la STL
Un peu de sérieux :-),
Je me suis orienté vers une liste chainé qui fonctionne (mais autrement plus dur à mettre en oeuvre)
Les classes std::list et std::vector ont toutes deux une méthode push_back, je ne vois pas la différence.
Dans ce code minimal, seul a et b sont pris en compte dans la liste.
Je ne peux pas mettre les variables c et d dans la fonction lisdf(), car je ne suis pas sur que cette fonction sera appelé, mais j'ai quand même besoin de récupérer la donnée.
Pas compris.
Voici le code que j'ai posté corrigé (je n'avais pas de quoi tester la dernière fois) :
#include <set> #include <string> #include <iostream> class mots_t{ public: typedef std::set<std::string> list_t; protected: static list_t list; public: mots_t(const std::string & mot){ list.insert(mot); } inline static const list_t & get_list() { return mots_t::list; } }; mots_t::list_t mots_t::list = mots_t::list_t(); int main(){ mots_t mots1("pouet"); mots_t mots2("plop"); // Accès à mots_t::list const mots_t::list_t & list = mots_t::get_list(); // Afficher les mots mots_t::list_t::const_iterator mots_it (list.begin()), mots_end(list.end()); for(;mots_it!=mots_end;++mots_it) std::cout << *mots_it << std::endl; return 0; }
et :
#include <set> #include <string> #include <iostream> typedef std::set<std::string> mots_t; /* // ou encore : class mots_t : public std::set<std::string> { //... }; */ int main(){ mots_t mots; mots.insert("plop"); mots.insert("pouet"); // Afficher les mots mots_t::const_iterator mots_it (mots.begin()), mots_end(mots.end()); for(;mots_it!=mots_end;++mots_it) std::cout << *mots_it << std::endl; return 0; }
Bonne chance
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 297
10 févr. 2010 à 08:11
10 févr. 2010 à 08:11
Merci, le problème, c'est que ta solution ne répond pas à mon problème.
Pourquoi est-ce normal que ça rende 2 ? J'ai fait appel 4 fois au constructeur (2 fois dans chaque fichier), la liste devrais donc avoir 4 comme taille. Quand je dit que le problème viens de la STL, c'est que ma liste semble réinitialisé entre les deux fichier (d'où une taille de 2). Alors que si j'utilise une liste chainé afin de gérer directement ce que je fait, il n'y a pas de souci, les pointeurs sont bien là et conservé. Il y a quelque chose qui m'échappe dans tout ça, mais il faudrait m'expliquer quoi...
Je vais essayer d'être plus précis dans l'explication de mon problème et de ce que je veux faire.
J'ai une cinquantaine de fichiers .cc, chacun de ces fichiers contient une fonction. Chaque fonction utilise une liste de mot. Mon but est récupérer et d'organiser ces listes de mots lors de l'exécution du programme. Mais comme je ne passe pas par toutes les fonctions, je suis obligé de mettre les définitions de mes variables en porté globale (en tout cas, je ne vois pas d'autre choix).
Voilà, j'espère que tes lumières m'éclaireront sur ce souci.
Pourquoi est-ce normal que ça rende 2 ? J'ai fait appel 4 fois au constructeur (2 fois dans chaque fichier), la liste devrais donc avoir 4 comme taille. Quand je dit que le problème viens de la STL, c'est que ma liste semble réinitialisé entre les deux fichier (d'où une taille de 2). Alors que si j'utilise une liste chainé afin de gérer directement ce que je fait, il n'y a pas de souci, les pointeurs sont bien là et conservé. Il y a quelque chose qui m'échappe dans tout ça, mais il faudrait m'expliquer quoi...
Je vais essayer d'être plus précis dans l'explication de mon problème et de ce que je veux faire.
J'ai une cinquantaine de fichiers .cc, chacun de ces fichiers contient une fonction. Chaque fonction utilise une liste de mot. Mon but est récupérer et d'organiser ces listes de mots lors de l'exécution du programme. Mais comme je ne passe pas par toutes les fonctions, je suis obligé de mettre les définitions de mes variables en porté globale (en tout cas, je ne vois pas d'autre choix).
Voilà, j'espère que tes lumières m'éclaireront sur ce souci.
mamiemando
Messages postés
33093
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
4 mai 2024
7 752
10 févr. 2010 à 11:26
10 févr. 2010 à 11:26
En fait pour moi ta structure qui référence les mots ne devraient pas être un membre statique de la classe mots, mais une instance à part entière (d'un point de vue design, ensuite d'un point de vue technique je vois bien pourquoi tu veux faire une variable statique).
Au niveau de l'incrément je n'avais pas compris que tu avais les deux fichiers ce que tu voulais mettre en évidence. En fait je ne pense pas que ça ait quelque chose à voir avec la stl.
a.hpp
main.cpp
donne :
Pour moi c'est toi qui utilises mal tes variables statiques ou le mot clé extern. En C et en C++,
- un symbole (fonction, variable) statique déclaré hors d'une fonction se comporte comme un symbole global au sein du fichier ;
- une variable statique dans une fonction est persistante entre deux appels de cette fonction
En C++ un membre statique (attribut ou méthode) n'est pas rattaché à une instance de classe. L'intérêt des membres statiques est de pouvoir définir une portée (protected, public...) et d'encapsuler ce membre dans une classe et ainsi de mieux architecturer le code.
En espérant que ça t'aide.
Au niveau de l'incrément je n'avais pas compris que tu avais les deux fichiers ce que tu voulais mettre en évidence. En fait je ne pense pas que ça ait quelque chose à voir avec la stl.
a.hpp
#include <set> #ifndef A_HPP #define A_HPP struct A{ static int n; static std::set<int> s; A(int c){ ++n; s.insert(c); } }; int A::n = 0; std::set<int> A::s = std::set<int>(); inline void g(){ A a5(5),a6(6); } #endif
main.cpp
#include <iostream> #include "a.hpp" void f(){ A a3(3),a4(4); } void display_set(){ std::set<int>::const_iterator sit (A::s.begin()), send(A::s.end()); std::cout << '{'; for(;sit!=send;++sit) std::cout << *sit << ' '; std::cout << '}' << std::endl; } int main(){ A a1(1),a2(2); std::cout << A::n << std::endl; display_set(); f(); std::cout << A::n << std::endl; display_set(); g(); std::cout << A::n << std::endl; display_set(); return 0; }
donne :
2 {1 2 } 4 {1 2 3 4 } 6 {1 2 3 4 5 6 }
Pour moi c'est toi qui utilises mal tes variables statiques ou le mot clé extern. En C et en C++,
- un symbole (fonction, variable) statique déclaré hors d'une fonction se comporte comme un symbole global au sein du fichier ;
- une variable statique dans une fonction est persistante entre deux appels de cette fonction
En C++ un membre statique (attribut ou méthode) n'est pas rattaché à une instance de classe. L'intérêt des membres statiques est de pouvoir définir une portée (protected, public...) et d'encapsuler ce membre dans une classe et ainsi de mieux architecturer le code.
En espérant que ça t'aide.
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 297
10 févr. 2010 à 12:29
10 févr. 2010 à 12:29
ça ne m'aide pas car je le sais déjà.
Je pense que tu as mal regardé le code exemple que j'ai fourni : je défini mes variables en dehors de toute fonction, je pense que c'est ça qui pose problème. Mais pourquoi ???
Si tu as le temps essai de compiler et de comprendre mes fichiers.
J'ai bien compris qu'une variable statique revenait à une variable globale (d'ailleurs dans le petit exemple que je donne j'utilise une variable globale) mais le fond du problème c'est que c'est un peu comme si elle se dupliquait entre les deux fichiers.
Un démonstrateur un peu plus propre :
demonstrate.h
def.cpp
main.cc
et un fichier machin.cpp :
Sortie :
Je pense que tu as mal regardé le code exemple que j'ai fourni : je défini mes variables en dehors de toute fonction, je pense que c'est ça qui pose problème. Mais pourquoi ???
Si tu as le temps essai de compiler et de comprendre mes fichiers.
J'ai bien compris qu'une variable statique revenait à une variable globale (d'ailleurs dans le petit exemple que je donne j'utilise une variable globale) mais le fond du problème c'est que c'est un peu comme si elle se dupliquait entre les deux fichiers.
Un démonstrateur un peu plus propre :
demonstrate.h
#include <vector> #include <string> #include <iostream> extern std::vector<char*> l; struct A{A(char* A);};
def.cpp
#include "demonstrate.h" std::vector<char*>l; struct A { A(char *a){l.push_back(a);std::cout<<a<<" constructeur\n";} };
main.cc
#include "demonstrate.h" A a("essai"); A b("essa2i"); int main() { std::cout<<l.size()<<"\n";// devrai rendre 4 for(int i=0;i<l.size();++i) std::cout<<l[i]<<"\n"; return 0; }
et un fichier machin.cpp :
#include "demonstrate.h" A c("dkjf"); A d("flgkfd"); void lisdf() { return; }
Sortie :
dkjf constructeur flgkfd constructeur essai constructeur assa2i constructeur 2 essai assa2i
mamiemando
Messages postés
33093
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
4 mai 2024
7 752
11 févr. 2010 à 02:38
11 févr. 2010 à 02:38
J'ai bien compris ton problème.
Par contre je me suis mal explqiuée dans mon message précédent. Le but de ma réponse était de te montrer :
1) comment utiliser les variables statiques,
2) te montrer que la stl n'a rien à voir avec ton problème.
Je vais te donner un exemple de code qui va à mon avis t'intéresser et qui se rapproche de ce que tu veux faire :
a.hpp
a.cpp
main.cpp
Ce qui donne :
Comme tu le vois le container STL (ici un std::set) n'a pas perdu de valeur et on est bien passé 4 fois dans le constructeur de A. Au niveau de ton code je ne sais pas ce qui cloche, mais un coup tu parles de static, un coup d'extern j'ai un peu de mal à voir.
Si l'on met de côté la question du comportement "2 au lieu de 4" de côté, je pense qu'il suffit simplement que tu utilises un design un peu plus propre comme celui que loupious a proposé (ou que j'ai proposé).
Bonne chance
Par contre je me suis mal explqiuée dans mon message précédent. Le but de ma réponse était de te montrer :
1) comment utiliser les variables statiques,
2) te montrer que la stl n'a rien à voir avec ton problème.
Je vais te donner un exemple de code qui va à mon avis t'intéresser et qui se rapproche de ce que tu veux faire :
a.hpp
#ifndef A_HPP #define A_HPP #include <iostream> void f(); struct A{ A(int); }; #endif
a.cpp
#include "a.hpp" #include <set> std::set<int> x; A::A(int a){ x.insert(a); std::cout << "adding " << a << std::endl; } void f(){ A a3(3); A a4(4); }
main.cpp
#include <set> #include <iostream> #include "a.hpp" extern std::set<int> x; template <typename T> std::ostream & operator << (std::ostream & out,const std::set<T> & s){ typename std::set<T>::const_iterator sit (s.begin()), send(s.end()); out << "{ "; for(;sit!=send;++sit) out << *sit << ' '; out << "}"; return out; } int main(){ std::cout << "0) " << x << std::endl; A a1(1); A a2(2); std::cout << "1) " << x << std::endl; f(); std::cout << "2) " << x << std::endl; return 0; }
Ce qui donne :
(mando@aldur) (~) $ g++ -c a.cpp (mando@aldur) (~) $ g++ main.cpp a.o (mando@aldur) (~) $ ./a.out 0) { } adding 1 adding 2 1) { 1 2 } adding 3 adding 4 2) { 1 2 3 4 }
Comme tu le vois le container STL (ici un std::set) n'a pas perdu de valeur et on est bien passé 4 fois dans le constructeur de A. Au niveau de ton code je ne sais pas ce qui cloche, mais un coup tu parles de static, un coup d'extern j'ai un peu de mal à voir.
Si l'on met de côté la question du comportement "2 au lieu de 4" de côté, je pense qu'il suffit simplement que tu utilises un design un peu plus propre comme celui que loupious a proposé (ou que j'ai proposé).
Bonne chance
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 297
11 févr. 2010 à 08:24
11 févr. 2010 à 08:24
Si l'on met de côté la question du comportement "2 au lieu de 4" de côté,
Oui, mais non, car c'est justement ça qui m'ennuie !
Tu remarquera que dans vos codes toutes les variables que vous utiliser son définies dans le corps d'une fonction. Moi, je les met en porté globale. Ceci n'est peut être pas très propre, mais je ne vois pas d'autre solution.
Pourquoi ? car, en reprenant ton exemple, je voudrais récupérer les valeurs passer à a3 et a4 avant d'appeler f() ou sans appelé f(). Ce n'est pas juste une torture de l'esprit, c'est comme je le disais le but de récupérer des informations disséminées dans une cinquantaine de fichiers, avec des fonctions qui ne sont pas forcément appelées (if(OPT) f();else g();). Il n'est pas souhaitable de rapatrier toutes ces données dans unique fichier/fonction car cela risque de créer des problèmes d'oublie ou de truc dans le genre lors des futurs développements.
C'est pour ça que je ne change pas le "design" de ce que je fais et que je m'entête à essayer de comprendre pourquoi mon démonstrateur ne fait pas ce que j'attends de lui. Pour les solutions alternatives, je pourrais peut être essayer d'illustrer mieux ce que j'ai et que je veux faire ?
Oui, mais non, car c'est justement ça qui m'ennuie !
Tu remarquera que dans vos codes toutes les variables que vous utiliser son définies dans le corps d'une fonction. Moi, je les met en porté globale. Ceci n'est peut être pas très propre, mais je ne vois pas d'autre solution.
Pourquoi ? car, en reprenant ton exemple, je voudrais récupérer les valeurs passer à a3 et a4 avant d'appeler f() ou sans appelé f(). Ce n'est pas juste une torture de l'esprit, c'est comme je le disais le but de récupérer des informations disséminées dans une cinquantaine de fichiers, avec des fonctions qui ne sont pas forcément appelées (if(OPT) f();else g();). Il n'est pas souhaitable de rapatrier toutes ces données dans unique fichier/fonction car cela risque de créer des problèmes d'oublie ou de truc dans le genre lors des futurs développements.
C'est pour ça que je ne change pas le "design" de ce que je fais et que je m'entête à essayer de comprendre pourquoi mon démonstrateur ne fait pas ce que j'attends de lui. Pour les solutions alternatives, je pourrais peut être essayer d'illustrer mieux ce que j'ai et que je veux faire ?
mamiemando
Messages postés
33093
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
4 mai 2024
7 752
11 févr. 2010 à 11:12
11 févr. 2010 à 11:12
Pourquoi ? car, en reprenant ton exemple, je voudrais récupérer les valeurs passer à a3 et a4 avant d'appeler f() ou sans appelé f().
Dans ce cas la il faut simplement faire un appel au niveau de A à cette fonction. Ou maintenir un membre statique dans A (ce sont les deux solutions que je t'ai proposé) ou appeler une méthode statique de A. Pas besoin d'extern dans ce cas.
Moi, je les met en porté globale. Ceci n'est peut être pas très propre, mais je ne vois pas d'autre solution.
Effectivement c'est sale, et en plus c'est sans doute la cause du problème. C'est d'ailleurs les raisons pour lesquelles je t'incite à changer de design.
C'est pour ça que je ne change pas le "design" de ce que je fais et que je m'entête à essayer de comprendre pourquoi mon démonstrateur ne fait pas ce que j'attends de lui. Pour les solutions alternatives, je pourrais peut être essayer d'illustrer mieux ce que j'ai et que je veux faire ?
En effet, car malgré tes explications je ne vois pas trop pourquoi tu ne fais pas une méthode statique comme loupious et moi te le suggérons depuis le début.
Dans ce cas la il faut simplement faire un appel au niveau de A à cette fonction. Ou maintenir un membre statique dans A (ce sont les deux solutions que je t'ai proposé) ou appeler une méthode statique de A. Pas besoin d'extern dans ce cas.
Moi, je les met en porté globale. Ceci n'est peut être pas très propre, mais je ne vois pas d'autre solution.
Effectivement c'est sale, et en plus c'est sans doute la cause du problème. C'est d'ailleurs les raisons pour lesquelles je t'incite à changer de design.
C'est pour ça que je ne change pas le "design" de ce que je fais et que je m'entête à essayer de comprendre pourquoi mon démonstrateur ne fait pas ce que j'attends de lui. Pour les solutions alternatives, je pourrais peut être essayer d'illustrer mieux ce que j'ai et que je veux faire ?
En effet, car malgré tes explications je ne vois pas trop pourquoi tu ne fais pas une méthode statique comme loupious et moi te le suggérons depuis le début.
loupius
Messages postés
697
Date d'inscription
dimanche 1 novembre 2009
Statut
Membre
Dernière intervention
31 décembre 2017
148
11 févr. 2010 à 14:40
11 févr. 2010 à 14:40
J'ai regardé ton post n° 8 et j'ai 2 remarques:
- tu passes de variable 'static' à 'global', il n'est pas facile de te suivre dans tes demandes,
- le code donné n'est pas compilable car la structure 'A' est déclarée 2 fois...
Comme mamiemando, j'ai un peu de mal à te suivre... ;-)
Pour les variables globales, il faut faire attention à l'ordre de déclaration des 'globales'.
Regarde les exemples suivants qui ne diffèrent que par l'ordre de déclaration:
radio
télé
table
chaise
fauteuil
lampe
table
chaise
fauteuil
lampe
Bonne réflexion.
- tu passes de variable 'static' à 'global', il n'est pas facile de te suivre dans tes demandes,
- le code donné n'est pas compilable car la structure 'A' est déclarée 2 fois...
Comme mamiemando, j'ai un peu de mal à te suivre... ;-)
Pour les variables globales, il faut faire attention à l'ordre de déclaration des 'globales'.
Regarde les exemples suivants qui ne diffèrent que par l'ordre de déclaration:
#include <string> #include <vector> #include <cstdlib> #include <iostream> using namespace std; class Mots { public: static vector<string> liste; Mots(string a) { liste.push_back(a); } }; vector<string> Mots::liste; Mots A("radio"); Mots B("télé"); void unDePlus(string str) { Mots mot(str); } int main(int argc, char *argv[]) { unDePlus("table"); unDePlus("chaise"); unDePlus("fauteuil"); Mots mot("lampe"); for (unsigned int i=0; i<Mots::liste.size(); i++) cout << Mots::liste[i] << endl; return EXIT_SUCCESS; }Résultat:
radio
télé
table
chaise
fauteuil
lampe
class Mots { public: static vector<string> liste; Mots(string a) { liste.push_back(a); } }; Mots A("radio"); Mots B("télé"); vector<string> Mots::liste; void unDePlus(string str) { Mots mot(str); } int main(int argc, char *argv[]) { unDePlus("table"); unDePlus("chaise"); unDePlus("fauteuil"); Mots mot("lampe"); for (unsigned int i=0; i<Mots::liste.size(); i++) cout << Mots::liste[i] << endl; return EXIT_SUCCESS; }Résultat:
table
chaise
fauteuil
lampe
Bonne réflexion.
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 297
12 févr. 2010 à 12:16
12 févr. 2010 à 12:16
Pour la compilation, en effet, peut être, je n'ai pas testé, il suffit dans def.cc de mettre A::A(char*) à la place de struct... J'ai écris ça rapidos juste pour vous montré ce que donne un démonstrateur un peu plus propre.
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 297
12 févr. 2010 à 12:25
12 févr. 2010 à 12:25
je regarde ton code, je n'arrive pas à voir la différence...
De plus, il manque radio et télé dans ton deuxième résultat.
Ce que tu as écris me conviens bien, MAIS si tu rajoutes un fichier .c avec des Mots dedans, est-ce qu'il apparaissent dans le résultat ?? chez moi non.
De plus, il manque radio et télé dans ton deuxième résultat.
Ce que tu as écris me conviens bien, MAIS si tu rajoutes un fichier .c avec des Mots dedans, est-ce qu'il apparaissent dans le résultat ?? chez moi non.
loupius
Messages postés
697
Date d'inscription
dimanche 1 novembre 2009
Statut
Membre
Dernière intervention
31 décembre 2017
148
>
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
12 févr. 2010 à 14:26
12 févr. 2010 à 14:26
La différence est l'ordre de déclaration entre les variables globales; il n'y a pas d'oubli dans le résultat, c'est rigoureusement ce que j'obtiens, mais cela peut peut-être dépendre du compilateur.
Une autre manière propre est d'utiliser aussi une fonction membre statique, par exemple:
Bonne continuation.
Une autre manière propre est d'utiliser aussi une fonction membre statique, par exemple:
mots.h #include <string> #include <vector> using namespace std; class Mots { public: static vector<string> liste; static void ajoute(string str) { liste.push_back(str); } }; fonction.cpp #include "mots.h" #include <iostream> void fonction1(void) { Mots::ajoute("radio"); Mots::ajoute("télé"); } void fonction2(void) { Mots::ajoute("lampe"); Mots::ajoute("fauteuil"); Mots::ajoute("lampe"); } void fonction3(void) { for (unsigned int i=0; i<Mots::liste.size(); i++) cout << Mots::liste[i] << endl; } main.cpp #include <cstdlib> #include "mots.h" using namespace std; vector<string> Mots::liste; extern void fonction1(void); extern void fonction2(void); extern void fonction3(void); int main(int argc, char *argv[]) { fonction1(); fonction2(); fonction3(); return EXIT_SUCCESS; } [loupius@p3000]$ g++ -Wall main.cpp fonction.cpp [loupius@p3000]$ ./a.out radio télé lampe fauteuil lampe [loupius@p3000]$A toi de choisir ce qui te convient le mieux.
Bonne continuation.
mamiemando
Messages postés
33093
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
4 mai 2024
7 752
>
loupius
Messages postés
697
Date d'inscription
dimanche 1 novembre 2009
Statut
Membre
Dernière intervention
31 décembre 2017
12 févr. 2010 à 14:29
12 févr. 2010 à 14:29
En même temps c'est un peu ce qu'on lui dit de faire depuis le début :-) Merci de poster en bas du fil de discussion.
loupius
Messages postés
697
Date d'inscription
dimanche 1 novembre 2009
Statut
Membre
Dernière intervention
31 décembre 2017
148
>
mamiemando
Messages postés
33093
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
4 mai 2024
12 févr. 2010 à 14:45
12 févr. 2010 à 14:45
Oui mais ne lui dites pas !
Il va peut-être finir par comprendre ... ;-))
Il va peut-être finir par comprendre ... ;-))
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 297
11 févr. 2010 à 14:43
11 févr. 2010 à 14:43
static ou global, c'est pareil.
Donc, pour essayer d'être plus clair. Voilà ce que j'ai actuellement (simplifier) :
fichier f.cc
fichier g.cc :
fichier main.cc
Et maintenant ce que je voudrais faire, c'est récupérer toutes les chaines de caractères (f_mot1, f_mot2, g_mot1 etc.) afin de les organiser et de les afficher.
Comme je ne peut pas appeler f et g dans le même processus, je ne passe pas dans tout le code et donc les variables c ne seront pas toutes définies. L'idée que j'ai eu c'est de toutes les regrouper en porté globale, comme ça moins de souci. Et ensuite avec mon constructeur je met toute ces variables dans une pile.
Autre contrainte, je voudrais qu'a l'avenir lorsqu'un dévellopeur rajoute une nouvelle fonction h() avec de nouveaux mots (h_mot1, h_mot2 ...) l'ajout à la liste se fasse simplement, presque automatiquement.
Voilà, j'espère avoir été plus clair.
Donc, pour essayer d'être plus clair. Voilà ce que j'ai actuellement (simplifier) :
fichier f.cc
void f() { const char* c={"f_mot1","f_mot2"...}; // ... if(variable==c[i]) // faire un traitement particluier dans ce cas là }
fichier g.cc :
void g() { const char* c={"g_mot1","g_mot2"...}; // ... if(variable==c[i]) // faire un traitement particluier dans ce cas là }
fichier main.cc
void f(); void g(); int main() { //... des trucs if(condition) f(); else g(); // ... d'autre trucs return 0; }
Et maintenant ce que je voudrais faire, c'est récupérer toutes les chaines de caractères (f_mot1, f_mot2, g_mot1 etc.) afin de les organiser et de les afficher.
Comme je ne peut pas appeler f et g dans le même processus, je ne passe pas dans tout le code et donc les variables c ne seront pas toutes définies. L'idée que j'ai eu c'est de toutes les regrouper en porté globale, comme ça moins de souci. Et ensuite avec mon constructeur je met toute ces variables dans une pile.
Autre contrainte, je voudrais qu'a l'avenir lorsqu'un dévellopeur rajoute une nouvelle fonction h() avec de nouveaux mots (h_mot1, h_mot2 ...) l'ajout à la liste se fasse simplement, presque automatiquement.
Voilà, j'espère avoir été plus clair.
mamiemando
Messages postés
33093
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
4 mai 2024
7 752
12 févr. 2010 à 11:55
12 févr. 2010 à 11:55
Justement, je t'ai donné au moins deux manières de le faire... proprement :-)
Dans ton cas les variables chaînes f_mot1... g_mot1 sont des variables locales à f() et g(), donc tu ne pourras pas les récupérer à moins de les copier quelque part (dans un objet instancié dans le main ou dans une variable globale par exemple).
Afin de les enregistrer, au lieu de faire un const char * en dur, il suffit d'enregistrer ces mots via une fonction ou une méthode. Voici pour moi les trois manières de faire ça :
- passer un std::set<std::string> (instancié dans main) et le passer à f() et g().
- pour éviter de passer ce set à toutes tes fonctions on peut imaginer qu'il soit global mais je suis pas fan.
- transformer f() et g() en d'un objet "plop" qui stocke ce std::set. Si "plop" peut être instancié plusieurs fois, on peut garantir l'unicité du std::set avec le mot clé statique.
Au cours de mes messages précédents j'ai donné avec loupious une manière de faire qui montrait cette approche de manière propre (la preuve... ça marche :p). Après, tu peux t'acharner avec tes extern et avec des morceaux de code bancales, mais il ne faut pas être surpris du résultat ^^ En soi je comprends ton problème qui consiste à te dire "mais pourquoi ça ne marche pas". Mon avis, c'est que plutôt que de se perdre dans des questions métaphysiques, il faut simplement coder proprement. Car au final, si j'ai bien compris ton propos, le but est d'avoir un code reprenable et maintenable. Du coup... je crois que tout est dit :-)
Dans ton cas les variables chaînes f_mot1... g_mot1 sont des variables locales à f() et g(), donc tu ne pourras pas les récupérer à moins de les copier quelque part (dans un objet instancié dans le main ou dans une variable globale par exemple).
Afin de les enregistrer, au lieu de faire un const char * en dur, il suffit d'enregistrer ces mots via une fonction ou une méthode. Voici pour moi les trois manières de faire ça :
- passer un std::set<std::string> (instancié dans main) et le passer à f() et g().
- pour éviter de passer ce set à toutes tes fonctions on peut imaginer qu'il soit global mais je suis pas fan.
- transformer f() et g() en d'un objet "plop" qui stocke ce std::set. Si "plop" peut être instancié plusieurs fois, on peut garantir l'unicité du std::set avec le mot clé statique.
Au cours de mes messages précédents j'ai donné avec loupious une manière de faire qui montrait cette approche de manière propre (la preuve... ça marche :p). Après, tu peux t'acharner avec tes extern et avec des morceaux de code bancales, mais il ne faut pas être surpris du résultat ^^ En soi je comprends ton problème qui consiste à te dire "mais pourquoi ça ne marche pas". Mon avis, c'est que plutôt que de se perdre dans des questions métaphysiques, il faut simplement coder proprement. Car au final, si j'ai bien compris ton propos, le but est d'avoir un code reprenable et maintenable. Du coup... je crois que tout est dit :-)
Char Snipeur
Messages postés
9696
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 297
17 févr. 2010 à 13:03
17 févr. 2010 à 13:03
Je met en résolu. Merci à Mamiemando et loupious pour leur patiences et leurs réponses.
En ce qui concerne ce que je cherchais à faire, les réponses donner sont assez clair, je n'y reviens pas.
En revanche, au sujet de pourquoi ce que j'ai fait ne fonctionne pas, j'ai à peu près compris, et tiens à résumé.
Le problème viens du fait que j'utilise des variables globales dans plusieurs fichiers et que suite à une compilation on n'est pas certain de l'ordre dans lequel ces variables seront appelées, du moins entre objet. Par exemple, si on a un fichier avec les variable a puis b et un autre avec c et d, on sait que b sera construit après a et d après c, mais on ne sais pas si ce sera abcd ou cdab.
Pour tester un peu, j'ai modifier ma variable statique contenue dans ma structure de vector à set comme le préconisait Mamiemando, j'ai alors eu des erreurs de segmentation, preuve que l'on n'avait pas encore construit la variable statique (similaire à une variable globale). Il apparait donc qu'avec un vector on peut utiliser cette variable sans l'avoir réellement construite.
Toujours pour tester, j'ai remplacé le constructeur classique de la variable statique :
std::vector<char*> A::l;
par
std::vector<char*>::iterator i1=A::l.begin(),i2=A::l.end(); // pas d'erreur car A::l est déclaré dans la structure
std::vector<char*> A::l(i1,i2);
Et avec cette modification mon problème disparait ! S'il on teste ceci sur le code donné en #12 par loupious, on obtient à nouveau la liste complète des mots dans le deuxième cas.
En ce qui concerne ce que je cherchais à faire, les réponses donner sont assez clair, je n'y reviens pas.
En revanche, au sujet de pourquoi ce que j'ai fait ne fonctionne pas, j'ai à peu près compris, et tiens à résumé.
Le problème viens du fait que j'utilise des variables globales dans plusieurs fichiers et que suite à une compilation on n'est pas certain de l'ordre dans lequel ces variables seront appelées, du moins entre objet. Par exemple, si on a un fichier avec les variable a puis b et un autre avec c et d, on sait que b sera construit après a et d après c, mais on ne sais pas si ce sera abcd ou cdab.
Pour tester un peu, j'ai modifier ma variable statique contenue dans ma structure de vector à set comme le préconisait Mamiemando, j'ai alors eu des erreurs de segmentation, preuve que l'on n'avait pas encore construit la variable statique (similaire à une variable globale). Il apparait donc qu'avec un vector on peut utiliser cette variable sans l'avoir réellement construite.
Toujours pour tester, j'ai remplacé le constructeur classique de la variable statique :
std::vector<char*> A::l;
par
std::vector<char*>::iterator i1=A::l.begin(),i2=A::l.end(); // pas d'erreur car A::l est déclaré dans la structure
std::vector<char*> A::l(i1,i2);
Et avec cette modification mon problème disparait ! S'il on teste ceci sur le code donné en #12 par loupious, on obtient à nouveau la liste complète des mots dans le deuxième cas.