121 votes

Pourquoi est-ce que C++ besoin d'un fichier d'en-tête?

Je n'ai jamais vraiment compris pourquoi C++ a besoin d'un distinct fichier d'en-tête avec les mêmes fonctions que dans le .fichier cpp. Il permet la création de classes et de refactoring très difficile, et il ajoute les fichiers inutiles pour le projet. Et puis il y a le problème d'avoir à inclure les fichiers d'en-tête, mais ayant explicitement vérifier si elle a déjà été inclus.

C++ a été ratifié en 1998, alors pourquoi est-il conçu de cette façon? Quels sont les avantages ayant un fichier d'en-tête?


Question de suivi:

Comment le compilateur trouver le .fichier cpp avec le code, quand je est la .h fichier? Elle n'assume que le .rpc fichier a le même nom que le .h fichier, ou est-elle vraiment regarder à travers tous les fichiers dans l'arborescence de répertoire?

99voto

Steve Jessop Points 166970

Vous semblez être de demander à propos de la séparation des définitions à partir des déclarations, bien qu'il existe d'autres utilisations pour les fichiers d'en-tête.

La réponse est que le C++ n'est pas "besoin" de cette. Si vous marquez tout en ligne (qui est de toute façon automatique pour les fonctions de membres définies dans une définition de classe), il n'est pas nécessaire pour la séparation. Il vous suffit de définir le tout dans les fichiers d'en-tête.

Les raisons que vous pourriez vouloir séparer sont:

  1. Pour améliorer les temps de construire.
  2. De lien à l'encontre du code sans avoir la source pour les définitions.
  3. Pour éviter le marquage tout "inline".

Si votre question plus générale est, "pourquoi n'est pas C++ identique à Java?", puis-je vous demander, "pourquoi écrivez-vous C++ au lieu de Java?" ;-p

Plus sérieusement, si, la raison en est que le compilateur C++ ne peut pas atteindre dans une autre unité de traduction et de comprendre comment l'utilisation de ses symboles, de la façon que javac peut et ne. L'en-tête de fichier est nécessaire de déclarer le compilateur à quoi il peut s'attendre à être disponibles au moment de la liaison.

Donc, #include est un droit textuelle de substitution. Si vous définissez le tout dans des fichiers d'en-tête, le préprocesseur finit par la création d'un énorme copier-coller de chaque fichier source de votre projet, et de l'alimentation que dans le compilateur. Le fait que la norme C++ a été ratifié en 1998 n'a rien à voir avec cela, c'est le fait que l'environnement de compilation en C++, est à base de si près à celle de C.

83voto

ongle Points 4567

C++ est-il de cette façon parce que C a elle de cette façon, la vraie question est donc pourquoi C le faire de cette façon? Wikipédia parle un peu de cela.

Nouveaux langages compilés (comme Java, C#) ne pas utiliser de l'avant les déclarations; les identificateurs sont reconnu automatiquement à partir de la source les fichiers et les lire directement à partir de dynamique bibliothèque de symboles. Cela signifie-tête les fichiers ne sont pas nécessaires.

56voto

jalf Points 142628

Certaines personnes considèrent que les fichiers d'en-tête d'un avantage:

  • Il est affirmé qu'il permet/applique/permet la séparation de l'interface et la mise en œuvre-mais généralement, ce n'est pas le cas. Fichiers d'en-tête sont plein de détails de mise en œuvre (par exemple les variables membres d'une classe doivent être spécifiés dans l'en-tête, même si ils ne font pas partie de l'interface publique), et les fonctions peuvent, et sont souvent, définie en ligne dans la déclaration de classe dans l'en-tête, de nouveau en train de détruire cette séparation.
  • Il est parfois dit pour améliorer le temps de compilation, car chaque unité de traduction peuvent être traitées indépendamment. Et pourtant, C est probablement le plus lent de la langue dans l'existence quand il s'agit de la compilation de fois. Une partie de la raison est le nombre répété de nombreuses inclusions de le même en-tête. Un grand nombre d'en-têtes sont inclus par plusieurs unités de traduction, les obligeant à être analysé à plusieurs reprises.

En fin de compte, le système d'en-tête est un artefact dans les années 70 quand le C a été conçu. À l'époque, les ordinateurs avaient que très peu de mémoire, et de garder l'ensemble du module de mémoire n'était tout simplement pas une option. Un compilateur avait pour démarrer la lecture du fichier en haut, puis linéaire sur le code source. L'en-tête mécanisme permet cela. Le compilateur n'a pas à envisager d'autres unités de traduction, il suffit de lire le code de haut en bas.

Et C++ conservé ce système pour assurer la compatibilité ascendante.

Aujourd'hui, il ne fait aucun sens. Il est inefficace, et sujettes à erreur d'être trop compliqué. Il y a de bien meilleures façons de séparer l'interface et la mise en œuvre, si c' était le but.

Cependant, l'une des propositions pour C++0x, était d'ajouter un module adéquat, permettant à code à compiler similaire .NET ou Java, en plus des modules, le tout en une seule fois et sans les en-têtes. Cette proposition n'a pas fait la coupe dans C++0x, mais je crois qu'il est encore dans le "nous aimerions le faire plus tard". Peut-être dans un TR2 ou similaire.

26voto

Michael Stum Points 72046

À mon (limité - je ne suis pas un développeur C normalement) de la compréhension, c'est enracinée dans C. Rappelez-vous que C ne sait pas ce que les classes ou les espaces de noms sont, c'est juste un programme long. En outre, les fonctions doivent être déclarées avant leur utilisation.

Par exemple, le suivant doit donner une erreur de compilateur:

void SomeFunction() {
    SomeOtherFunction();
}

void SomeOtherFunction() {
    printf("What?");
}

L'erreur doit être "de SomeOtherFunction n'est pas déclaré" parce que vous l'appelez avant de déclaration. Un moyen de fixation est de passer SomeOtherFunction ci-dessus SomeFunction. Une autre approche consiste à déclarer les fonctions de la signature de la première:

void SomeOtherFunction();

void SomeFunction() {
    SomeOtherFunction();
}

void SomeOtherFunction() {
    printf("What?");
}

Cela permet au compilateur de savoir: Chercher quelque part dans le code, il y a une fonction appelée SomeOtherFunction void et ne prend aucun paramètre. Donc, si vous rencontrons code qui tente de l'appeler SomeOtherFunction, ne paniquez pas et au lieu d'aller le chercher.

Maintenant, imaginez que vous avez SomeFunction et SomeOtherFunction dans deux différents .c fichiers. Ensuite, vous devez #include "SomeOther.c" dans Certains.c. Maintenant, ajouter un peu de "privé" fonctions de SomeOther.c. Comme C ne sait pas privé des fonctions, que la fonction est disponible dans Certains.c ainsi.

C'est où .h Fichiers: Ils spécifier toutes les fonctions (et variables) que vous souhaitez à "l'Exportation" de une .c fichier qui peut être consulté dans d'autres .c fichiers. De cette façon, vous gagnez quelque chose comme un Public/Privé de la portée. Aussi, vous pouvez donner ce .h fichier à d'autres personnes sans avoir à partager votre code source .h les fichiers de travail contre compilé .fichiers lib.

Donc, la raison principale est vraiment pour des raisons de commodité, le code source de protection et d'avoir un peu de découplage entre les parties de votre application.

Que C était bien. C++ a introduit les Classes et privé/public modificateurs, donc pendant que vous pourrait encore se demander si elles sont nécessaires, C++, autant que je sache encore besoin d'une déclaration de fonctions avant de les utiliser. Aussi, de nombreux Développeurs C++ sont ou ont été C devleopers ainsi et ont pris possession de leurs concepts et les habitudes de C++ - pourquoi changer ce qui n'est pas cassé?

10voto

erelender Points 3634

Premier avantage: Si vous n'avez pas de fichiers d'en-tête, vous devez inclure les fichiers source dans d'autres fichiers source. Ce serait la cause de la y compris les fichiers à compiler à nouveau lorsque les modifications apportées au fichier.

Deuxième avantage: Il permet de partager les interfaces sans partage de code entre les différentes unités (différents développeurs, équipes, entreprises, etc..)

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