27 votes

C++ mot-clé extern sur les fonctions. Pourquoi pas il suffit d'inclure le fichier d'en-tête?

Si je comprends bien, cela signifie

extern void foo();

que la fonction foo est déclaré dans une autre unité de traduction.

1) Pourquoi ne pas simplement #inclure l'en-tête dans lequel cette fonction est déclarée?

2) Comment fonctionne l'éditeur de liens de savoir où chercher pour fonction de relier le temps?

edit: je devrais Peut-être préciser que la déclaration ci-dessus est suivie par l'aide de la fonction

foo();

Il n'est jamais défini dans cette unité de traduction.

21voto

Brian Neal Points 13668

1) Il ne peut pas avoir un fichier d'en-tête. Mais oui, en général, pour les grands projets, vous devriez avoir un fichier d'en-tête si plusieurs unités de traduction vont utiliser cette fonction (don't repeat yourself).

2) L'éditeur de liens recherche dans tous les fichiers de l'objet et des bibliothèques, il a été dit au sujet de trouver des fonctions et d'autres symboles.

9voto

goedson Points 400

Comme d'autres l'ont déjà dit, l' extern mot clé est utilisé pour indiquer le nom (une variable ou une fonction) a une liaison externe, ce qui signifie le nom fait référence au même objet dans l'ensemble du programme. Aussi, c'est la valeur par défaut pour les variables et les fonctions définies dans le fichier de portée, si cette utilisation est superflu.

Il y a une autre utilisation du mot-clé extern qui va comme ceci:

extern "C" void foo();

Cela signifie que la fonction foo sera liée à l'aide du C conventions pour le lien (peut-être parce que c'est une fonction définie dans une bibliothèque C ou est une fonction destinée à être appelés par les programmes en C).

7voto

Hans Passant Points 475940

Il signifie déjà que sans le mot-clé extern. Les fonctions ont une liaison externe par défaut, sauf si vous déclarez statiques.

À l'aide de prototypes de fonction est ok, mais c'est facile de se tromper. L'éditeur de liens d'erreur que vous obtenez n'est pas facile de diagnostiquer lorsque vous redéfinir la fonction de mise en œuvre. L'éditeur de liens ne savez pas où chercher, il est de votre devoir de lui donner un objet de fichier qui contient la définition de la fonction pour le garder heureux.

6voto

AndreyT Points 139512

Non, cela signifie que la fonction foo est déclarée avec une liaison externe. Liaison externe signifie que le nom de l' foo se réfère à la même fonction, dans l'ensemble du programme. Où la fonction est définie n'a pas d'importance. Il peut être défini dans cette unité de traduction. Il peut être défini dans d'autres unités de traduction.

À l'aide de extern mot-clé comme indiqué dans votre exemple est superflu. Les fonctions de toujours avoir une liaison externe par défaut. Le ci-dessus est de 100% équivalent à la juste

void foo();

Comme pour l'éditeur de liens, lorsque l'éditeur de liens liens le programme ensemble, il a tout simplement l'air partout. Il regarde à travers toutes les définitions jusqu'à ce qu'il trouve la définition de l' foo.

2voto

BjoernD Points 2712

1) je ne sais pas pourquoi j'avais besoin de cela pour une fonction. Peut-être que quelqu'un d'autre peut intervenir.

2) L'éditeur de liens détermine ce qu'en passant par tous les fichiers objets et de vérifier les symboles à l'intérieur de chaque fichier de l'objet. Je suppose qu'en fonction de votre éditeur de liens, la recherche exacte peut varier.

Pour GNU binutils' ld tous les fichiers et bibliothèques d'objets qui apparaissent dans l'éditeur de liens de ligne de commande après l'objet contenant le symbole manquant sont recherchés à partir de la gauche vers la droite et le premier symbole est repris.

Exemple 1:

  • un.o -- utilise foo(), bar()
  • liba -- offre bar()
  • libb -- fournit des foo()

$> ld a.o -la-lb

le résultat sera une.o en cours de recherche pour les symboles non définis. Par la suite, ld passera par le syndicat de gauche à droite à la recherche de ces symboles et de trouver les bar dans liba et toto dans libb.

Cela peut conduire à des problèmes étranges sur les dépendances circulaires:

Exemple 2:

  • un.o -- utilise bar()
  • liba -- offre bar(), utilise foo()
  • libb -- fournit des foo(), utilise la barre()

Maintenant, il y a une dépendance circulaire entre liba et libb et la liaison ne fonctionne pas:

$> ld a.o -la-lb

parce que lors de la recherche à travers les symboles non définis dans libb, ld permettra de déterminer qu'il n'existe pas d'autres lib pour le droit de lb qui fournit ce symbole. Ce peut être fixé de deux façons au moins:

1) lien liba deux fois: $> ld a.o -la-lb -la

2) utiliser ld la fonctionnalité de regroupement $> ld a.o --start-groupe -de-la-lb-fin-groupe

Dans le cas 2), le groupement raconte ld à la recherche par le biais de tous les symboles de toutes les libs appartenant à ce groupe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X