J'adorerais aider à diagnostiquer la source d'une erreur de symbole dupliquée que je reçois lorsque j'essaie de compiler avec g ++ 4.2.1.
L'erreur spécifique est p> L'erreur se produit uniquement lorsque j'inclus cette déclaration dans un fichier appelé J'ai recherché tous mes fichiers, et c'est le seul endroit où Je suis inconnu avec des erreurs de liaison (si c'est ce que cela est) et apprécierait l'aide pour résoudre le problème. Tous mes fichiers d'en-tête ont merci d'avance. P> << i ont maintenant dans les paramètres.h: p> toutes les autres définitions et déclarations dans les paramètres.h sont inchangées. Andrey et d'autres commentateurs résument une approche alternative utilisant paramètre.h p>: p>: p>: p>:
sociodem_filenames code> est déclaré. Lorsque je commente la déclaration, l'erreur «symbole dupliquée» disparaît. P>
#ifndef ... # définir ... # endif code> wrappers. Ma commande compile est p>
externe code>, qui est excédant à mes fins. P> p>
5 Réponses :
La garde d'en-tête ( #Ifndef .. # endif code> wrapper) vous empêche d'inclure la même en-tête plusieurs fois dans un seul fichier source. Vous pouvez toujours avoir plusieurs fichiers source incluant cet en-tête et chacun déclarera ce symbole séparément. Comme ils ont tous le même nom, lier ces sources ensemble provoquera une collision de noms de symboles. Vous voulez probablement déclarer le symbole dans un fichier source au lieu d'un fichier d'en-tête p>
Le problème est que vous mettez une définition dans un fichier d'en-tête. Si vous incluez ce fichier dans plusieurs unités de compilation (fichier .cpp), vous obtiendrez de multiples définitions et au moment de la liaison, vous obtiendrez cette erreur.
Vous devez mettre à la fois ces définitions dans un fichier .CPP et Mettez Seulement em> une déclaration dans le fichier d'en-tête: p>
Très probablement, vous êtes Ce que vous devez faire est de déclarer ces variables comme et ensuite: p> Vous pouvez vous échapper sans le faire pour le #include code> ce fichier dans plusieurs fichiers source. Le problème est que chaque inclusion entraîne une définition distincte pour une variable nommée
sociodem_filenames code>. Inclure les gardes n'aident pas avec cela. Inclure les gardes empêchent de multiples déclarations em> dans une seule unité de compilation; ils n'empêchent pas plusieurs définitions em> sur plusieurs unités de compilation.
extern code> dans l'en-tête, puis de les définir exactement fichier source. par exemple p>
int Code> Parce qu'il s'agit d'un entier constant, le compilateur peut donc simplement le traiter comme une constante de temps de compilation, et elle ne se présentera même jamais dans le code compilé. Cependant, le
Char * code> ne peut pas être traité de cette manière, et doit donc avoir exactement une définition (appelée «règle de définition» en C ++). P> P>
Qu'entendez-vous par les paramètres Int et Double «N'ayez même jamais montré [ING] dans le code compilé»? Tous mes autres paramètres étaient de type numérique constant et semblaient être présents dans le code compilé.
Je veux dire que le compilateur n'a pas nécessairement besoin de créer des emplacements de mémoire pour stocker ces chiffres lorsque le programme est exécuté. Essentiellement, le compilateur peut le traiter presque comme si vous écrivez #define num_sociodem_files 5 code> et il suffit de remplacer la variable avec le littéral
5 code> où qu'il soit utilisé. La règle d'une définition existe pour que chaque variable nommée puisse être mappée sur un emplacement de mémoire unique et unique. Si un emplacement de mémoire n'est pas requis, le problème est moot.
Déplacement de la définition num_sociiodem_files code> sur le fichier .cpp est en réalité une mauvaise idée. Les objets Const Scalar sont normalement définis dans les fichiers d'en-tête. Il n'y a rien de mal à cela et en fait, il y a beaucoup de choses avec ça. Dans de nombreux cas, il est extrêmement utile d'avoir
num_sociodem_files code> comme une expression constante intégrale. Cette réponse a détruit cette valeur précieuse de
num_sociodem_files code> sans raison.
Comme d'autres ont suggéré, une façon de le faire est de déclarer num_sociodem_files code> et
sociodem_filenames code> comme
extern code> et les définir une fois dans un fichier externe . L'autre sens est de les déclarer comme
statique code> - cela leur permet d'être dupliqués dans chaque fichier d'objet qui inclut l'en-tête, mais ne créera pas d'erreur car la définition est privée dans ce fichier d'objet. Quelle option que vous choisissez est entièrement à vos préférences. P>
Merci. N'avait pas su cette option.
C'est dangereux si vous ne comprenez pas complètement ce que cela signifie - cela crée une instance séparée de ces variables dans chaque fichier d'objet. C'est probablement bien (bien que peu inefficace) dans ce cas, puisqu'il s'agit de Const, mais si vous l'avez fait avec une variable mutable et l'a changé dans un fichier, seule l'instance de ce fichier changerait
Je ne prévoyais pas d'aller dans cette voie pour cette raison, mais je n'ai pas réalisé que «statique» créerait des copies distinctes pour chaque fichier. J'apprécie l'avertissement.
@Sarah Static signifie que le symbole est local dans le fichier d'objet qui le contient. Il "corrige" l'erreur car maintenant tous vos fichiers source ont toujours les mêmes symboles avec le même nom, mais les symboles sont locaux au lieu de Global pour ne pas entrer en collision entre eux.
Pour une raison quelconque, aucune des réponses ne se souciait jusqu'à présent d'expliquer la différence entre votre entier La raison en est que votre objet C'est pourquoi il ne conduit à aucun problème de liaison. P> < P> En même temps, votre note où le supplément < Code> Const code> est placé dans la déclaration. Si vous ajoutez simplement cet extra Ce n'est pas une approche recommandée cependant, car de cette façon, vous donnerez votre Toutefois, note que vous ne devriez pas normalement le faire pour num_sociiodem_files code> objet et tableau
sociodem_filenames code> objet. Ce dernier déclenche l'erreur de liaison pour les raisons déjà expliquées: parce que vous incluez votre fichier d'en-tête en plusieurs fichiers de mise en œuvre. Cependant, le premier lienait sans aucun problème (car il n'y a bien aucun problème avec
num_sociiodem_files code> déclaration). Pourquoi?
num_sociiodem_files code> est déclaré
const code>. Dans C ++, des objets Constons ont lien interne em> par défaut, ce qui signifie qu'ils ne causent pas de problèmes de liaison, même s'ils sont définis dans plusieurs fichiers de mise en œuvre. En d'autres termes, en C ++ votre
num_sociodem_files code> est équivalent à p>
sociodem_filenames code> n'est pas déclaré constant, c'est pourquoi il obtient lien externe em> par défaut et conduit éventuellement à des erreurs de liaison. Mais si vous déclarez votre
sociodem_filenames code> comme
const code> aussi, le problème disparaîtra p>
const code> et laissez tout le reste tel qu'il est (c.-à-d. Garder la définition si
sociodem_filenames code> dans le fichier d'en-tête), le linker ne signalera pas l'erreur même si vous Indiquez votre fichier d'en-tête en plusieurs unités de traduction. P>
sociodem_filenames code> liaison interne et finissez avec une copie autonome de < Code> SocioDem_Filenames Code> Array dans chaque unité de traduction - quelque chose qui pourrait fonctionner bien mais il est toujours très peu de sens. Donc, pour votre tableau, il est normalement préférable d'utiliser l'approche
extern code> recommandée dans d'autres réponses. P>
num_sociiodem_files Code> Déclaration !!! C'est bien tel qu'il est, défini dans le fichier d'en-tête. Sauf si vous essayez de faire quelque chose d'inhabituel, les constantes scalaires devraient normalement être définies avec Initializer EM> dans les fichiers d'en-tête - de cette façon, ils peuvent être considérés comme des constantes de compilation dans toutes les unités de traduction, ce qui est un assez précieux chose à avoir. Ainsi, méfiez-vous de l'étrange conseil présent dans d'autres réponses pour déplacer la définition de
num_sociodem_files code> dans
.cpp code> fichier également - cela n'a aucun sens et est une chose totalement erronée faire. p> p>
Wow merci. Cela explique beaucoup. Cela a résolu à peu près le même problème pour moi.
Super. Pourtant, je ne comprends toujours pas pourquoi vous ne déclarez pas votre
sociodem_filenames code> tableau comme
const code>. Les entrées de réseau sont-elles censées être modifiables au moment de l'exécution?
@Andrey: Je devrais les déclarer comme constante. Merci.