0
votes

Compréhension de l'erreur de lieur C: Définition multiple

J'ai un projet avec plusieurs fichiers d'en-tête et .cpp . Tous les fichiers d'en-tête ont inclus des gardes.

Il existe un fichier appelé constantes.h où je définis des constantes. Certaines d'entre elles qui définissent, certaines variables constantes.

Il y a plus d'en-tête - .CPP -File paires avec code dans celui-ci. L'un d'entre eux contient une classe, les autres ne le font pas.

Lorsque j'inclus mes fichiers dans mon fichier principal (un croquis Arduino), je reçois beaucoup d'erreurs de liaison, réclamant plusieurs définitions de certaines variables.

J'ai lu que cela se produit principalement lorsque vous incluez .c ou .cpp fichiers que je ne fais pas. Tous les fichiers .cpp n'incluent que leurs fichiers d'en-tête appropriés.

J'ai réussi à trouver plusieurs propositions de solution:

1) inline :

avec fonctions, en ligne peut être utilisé pour se débarrasser de ce problème. Cependant, cela n'est pas possible avec des variables.

2) anonyme espace de noms :

C'est l'une des solutions que j'ai utilisées. Je mets des espaces de noms anonymes autour de toutes les définitions problématiques que j'ai eues. Cela a fonctionné, mais je ne comprends pas pourquoi cela fonctionne. Quelqu'un pourrait-il m'aider à le comprendre?

3) Définitions mobiles en .cpp fichiers:

C'est une autre approche que j'ai utilisée parfois, mais ce n'était pas toujours possible car j'avais besoin de certaines de mes définitions dans d'autres codes, n'appartenant pas à ce fichier d'en-tête ou son code (ce que j'admets, c'est une mauvaise conception).

Quelqu'un pourrait-il m'expliquer où réside exactement le problème et pourquoi ces approches fonctionnent?


4 commentaires

@NathanOniver - Cette question concerne une différence subtile entre C et C ++. Que Dupe est des ordures.


@Storyteller Il y a un fichier appelé Constantes.h où je définis des constantes. Certaines d'entre elles avec définissent, certaines comme variables constantes. ressemble à une coupe assez transparente dupe de l'OP incluse les définitions variables de plusieurs turs.


@Nathanoliver - Sauf in C ++ const quelle que soit la barre = foo; au champ d'espace de noms a une liaison interne par défaut.


Y a-t-il un code C impliqué? Sinon, vous pourriez supprimer la balise de langage C.


3 Réponses :


3
votes

Certaines d'entre elles avec définissent, certaines comme variables constantes.

in c const n'implique pas la même chose que dans C ++. Si vous avez ceci: xxx

dans une en-tête, alors une unité de traduction C ++ qui inclut l'en-tête aura une variable statique nommée foo (le const à la portée des espaces de noms implique une liaison interne). De plus, FOO peut même être considéré comme une expression constante de nombreuses constructions C ++.

tel n'est pas le cas dans C. Là FOO est un objet à Portée de fichiers avec liaison externe. Donc, vous aurez de multiples définitions d'unités de traduction C.

une solution rapide serait de modifier les définitions en quelque chose comme ceci: xxx

ceci est redondant en C ++ mais requis dans C.


2 commentaires

Cela a vraiment effacé beaucoup. Ajouter statique aux définitions problématiques du truc. Je suis juste surpris que je n'ai jamais trébuché à travers cela avant ...


@Lithimlin - Normalement, les en-têtes ne auront pas d'objets comme ça. Et les en-têtes C ++ auront d'autres choses qui sont bien plus susceptibles de ne pas être valables C.



2
votes

En plus de l'excellente explication de l'histoire de l'histoire, de définir les variables globales, utilisez ce qui suit: xxx

dans main.c toutes les variables seront déclarées (c.-à-d. est alloué pour eux), dans tous les autres fichiers C incluant glo.h , toutes les variables seront connues.


0 commentaires

0
votes

Vous ne devriez pas déclarer aucun objet dans les fichiers d'en-tête, cela doit être déplacé vers des fichiers C \ C ++.

En en-tête, vous pouvez:

  • Déclarez des types tels que: Classe ES, struct S, Typef s etc.
  • Publier des déclarations de fonctions (non classes)
  • mettre des fonctions en ligne (ou dans des classes) (+ corps)
  • Vous pouvez ajouter externe Déclaration.
  • Vous pouvez mettre vos macros.

    A Static La déclaration peut déclarer des choses plusieurs fois, donc il n'est pas recommandé.


2 commentaires

Les déclarations vont bien. Les définitions sont ce qui cause des problèmes.


Je conteste votre fausse assertion avec consexpr double epsilon = 1e-6;