variable globale, problème de link - C++ - Programmation
Marsh Posté le 02-09-2004 à 10:36:06
Taz a écrit : rien compris, balance du code (3 lignes et pas plus) |
init.h :
struct s_ini{
int nCalib;
BOOL bHtmlResume;
string szFilePath;
double dEvUrbach0;
double dEvUrbach1;
double dEvdefauts;
double dEvcrist;
int nType;
};
void read_init_file(struct s_ini & init, string szFileName="x" ); //fonction qui remplis les champs d'une struct
struct s_ini init_data; //déclaration variable globale
///////////////////////////////////////////
init.cpp
initialisation de la variable globale :
BOOL CEx06aView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
read_init_file(init_data);
return CView::PreCreateWindow(cs);
}
Puis par exemple, dans diverses classes, appel aux données de cette structure :
void CEx06aView::OnCpm()
{
//blabla
index_urbach0=c.get_ev_index(init_data.dEvUrbach0);
index_urbach1=c.get_ev_index(init_data.dEvUrbach1);
//blabla
}
mais dans les methode des classe, cette variable globale est utilisée, et non définie...
(bon je sais, 3 lignes )
Marsh Posté le 02-09-2004 à 10:42:14
1/ dans init.h : pas de déclaration de la variable globale init_data
2/ dans init.cpp : tu déclare struct s_ini init_data;
3/ dans les autres cpp : tu déclare extern struct s_ini init_data;
Marsh Posté le 02-09-2004 à 11:08:53
+1
Pour éviter d'avoir à redéclarer X fois "extern xxx" dans tous les cpp, un truc : la compile conditionnelle.
Code :
|
Code :
|
Code :
|
L'autre (gros) avantage, c'est que tes déclarations (allocation et référence "extern" ) sont regroupées dans le même fichier. Quand tu modifie d'un côté, la modif parallèle se trouve juste en dessous.
Sinon bonjour les dégats si les deux ne correspondent pas...
Marsh Posté le 02-09-2004 à 11:12:54
+1
Déjà qu'il assimile cette histoire de variable globale et ce sera bien.
Marsh Posté le 02-09-2004 à 11:29:23
1. init.h
2. .../...
3. #ifdef ALLOC_GLOBAL
4. int toto;
5. int tata = 93893; //Avec une valeur de départ
6. MaStruct titi;
7. #else
8. extern int toto;
9. extern int tata; //!!! Ne pas redonner de valeur avec "extern"
10. extern MaStruct titi;
11. #endif
c'est complètement pourri ta façon de procéder, c'est source d'erreur
un .h avec les déclarations extern, un .cpp avec l'allocation des variables
Marsh Posté le 02-09-2004 à 12:16:49
Taz a écrit : 1. init.h |
+1.
Encore mieux, serait de passer par une fonction qui te renvoie un singleton. Du style:
Code :
|
Ca évite pas mal de problèmes lors de l'utilisation de l'instance avant le démarrage de main().
Edit: j'avais oublié un type.
Marsh Posté le 02-09-2004 à 13:21:01
Merci pour votre aide, je vais essayer.
C'est vrai que les variables globales je ne maîtrise pas, car je m'en suis toujours passé jusqu'à présent...
EDIT :
j'ai utilisé la technique de pains-aux-raisins, et ça marche très bien. J'avais complétement oublié le coup du external. Encore merci
Marsh Posté le 02-09-2004 à 13:51:56
Sur l'exemple de Lam's : et la struct on la libère pas ?
http://forum.hardware.fr/hardwaref [...] 5867-1.htm
Marsh Posté le 02-09-2004 à 13:53:35
bien essayé, mais n'attends pas trop de quelqu'un qui ne manipule que des struct ...
Marsh Posté le 02-09-2004 à 14:01:53
BlackGoddess a écrit : Sur l'exemple de Lam's : et la struct on la libère pas ? |
Bof, ça sert à rien de la détruire si sa durée de vie est celle du programme. Sinon, tu rajoutes ça dans ton cpp
Code :
|
Voilà, c'est assez "spirit of the C++" pour vous ?
Sinon, je tenais à dire par rapport au topic que tu as lié, que je suis un fervent opposant au singleton façon GoF : ça marche très mal lors de l'initialisation des variables statiques.
Marsh Posté le 02-09-2004 à 14:12:54
Taz a écrit : |
Merci, Taz, apparemment tu serais l'unique personne a maîtriser l'unique technique de codage. Comme s'il en existait qu'une seule. Je parle des techniques et non des personnes. Parce que des personnes qui pensent détenir le savoir unique : désolé mais tu n'est pas le seul. Sans parler de CET exemple précis, simplement quand tu critiques un post - que ce soit de manière négative ou même positive - ça serait pas mal d'expliquer pourquoi.
Maintenant, pour reprendre CET exemple :
- qqu'un pose une question précise et cherche des réponses précises à SON problème.
- il n'est pas forcément très utile de refaire le monde en général et le débat sur les variables globales en particulier
- "c'est source d'erreur un .h avec les déclarations extern". Par curiosité, as-tu déjà parcouru les fichiers .h de ton compilateur ? Curieux, avec mon compilo (C++ Builder) je trouve des centaines de déclarations de variable globales en "extern".
Pour Lam's :
T'aurais pas *encore* plus compliqué ?
Où as-tu vu que la structure à allouer était un objet avec un constructeur ?
Quel est le besoin impératif de passer par un "new" ?
Une bonne vieille variable globale ne serait-elle pas plus simple ?
Ok, ok, il y a des risques (quelle façon de procéder n'en a pas ???) avec les globales. La soluce s'appelle : test et debug.
Marsh Posté le 02-09-2004 à 14:19:45
lsdyoyo a écrit : |
Oh, j'aurais pu passer par un template, c'est vrai
Nan, plus simplement, le premier bout de code que j'ai posté est ce que j'ai trouvé de plus "efficace" pour mes problèmes de variable globales de manière générale. Une variable globale peut poser beaucoup de problèmes (comme tu le dit, on va pas refaire le débat).
Le deuxième bout de code, c'est plus une moquerie aux "puristes" du C++.
Quand au new, c'est pour éviter de passer par les références, qui peuvent souvent être confuses. Pas besoin de constructeur pour ça.
Maintenant, la meilleure solution, elle existe : c'est celle que l'on comprend, qui fonctionne, et qui demande le moins de temps à implémenter et à maintenir. Donc à chaque développeur ses petites habitudes...
Voilà, pas besoin de se facher...
Marsh Posté le 02-09-2004 à 14:28:25
lsdyoyo > commence par comprendre ce que je dis et arrête de transformer mes propos.
Marsh Posté le 02-09-2004 à 14:47:56
Tu voulais peut-être faire :
- Dans le .h : les extern
- Dans un seul des .cpp : les allocations
Pourquoi pas ? Je trouve très bien d'avoir les deux dans un .h : un seul fichier à modifier/vérifier.
En quoi est-ce "pourri" ?
Marsh Posté le 04-09-2004 à 00:42:22
oui, il faut faire comme ça, c'est la matière canonique. pourquoi ? parce qu'en fin de compte, c'est la même chose que tu fais avec ton #define conditionel : la présence de l'allocation dans une seule unité de traduction. Alors entre gérer ça à la main, avec les risques d'erreurs, et se contenter de faire un fichier, y a pas à choisir. sinon n'oublie pas de faire exactement la même chose pour toutes les fonctions, interdis toi les .c (allez, je te laisse le main).
Marsh Posté le 04-09-2004 à 15:05:44
Taz a écrit : 1. init.h |
A la limite, il peut définir les valeurs dans le .h, mais dans ce cas, il faut les définir en constantes :
const int tata = 93893;
Ne pas oublier de proteger le fichier contre l'inclusion multiple aussi, des fois que, dans un sursaut d'étourderie ...
Marsh Posté le 04-09-2004 à 15:29:06
ouais c'est que je dis, c'est source d'erreur ce truc, ça fait 20 ans qu'on fait un .h et un .c on va se faire chier à faire une méthode qui est dangereuse
Marsh Posté le 21-04-2005 à 11:05:24
lsdYoYo a écrit : +1
|
Je confirme les propos de Taz quant à dire que c'est source d'erreurs ; par exemple lorsqu'on compile son programme "bout par bout".
Je m'explique : pour les gens qui utilisent visual sans vouloir se faire chier avec les makefile (j'en fait parti :-D), voilà une situation foireuse :
2 fichiers .cpp incluent init.h
si à la compilation le premier compile bien, le 2eme foire, quand on va recompiler, il ne recompilera pas le 1er (qui a "en lui" la variable globale de créée) et va en recréer une pour le second, la macro ALLOC_GLOBAL étant "nouvelle"
Maintenant il me manque surement des connaissances de configuration de visual...
Marsh Posté le 02-09-2004 à 08:51:37
Bonjour, j'ai un autre problème à vous soumettre :
Plutôt que de définir des constantes fixes dans mon programme, j'ai créé un fichier dans lesquelles elles sont réunies, de façon à ce que chaque utilisateur puisse avoir son propre fichier de configuration avec des valeurs différentes.
Pour introduire ces données dans le programme, j'ai créé une structure dont chaque champ correspond à un paramètre de configuration. Par exemple nom_structure.szDefaultPathName etc. j'ai ensuite une fonction qui prends comme argument une de ces structures, et remplis les champs en fonction du fichier.
Vu que j'ai besoin d'accéder au champs de cette structure dans tous le programme (c'est à dire dans toutes les classes, à chaque fois qu'un des paramètres constant provenant du fichier doit être insérer), j'ai créé une variable globale de la structure d'initialisation, et je l'utilise parout où c'est nécessaire.
J'ai un fichier init.h avec la définition de la structure, le prototype de la fonction d'initialisation, et la déclaration de la variable globale du type de la structure. Le fichier init.cpp contient l'implémentation de la fonction d'initialisation.
Pas de problèmes de compilation, mais au moment du linkage, j'obtiens des messages d'erreur du genre :
Cpmdiag.obj : error LNK2005: "struct s_ini init_data" (?init_data@@3Us_ini@@A) already defined in cpm.obj
Mais struct s_ini init_data n'est DEFINIE que dans le fichier init.h, dans les autres fichiers, cette variable globale est utilisée, mais pas redéfinie...
j'utilise VC++6.0, et en configuration DEBUG, le programme est quand même créé (comme s'il s'agissait plus de warnings que d'erreur), mais en RELEASE, pas question de finir le linkage...
Ou me suis-je trompé?