web-dev-qa-db-fra.com

Comment inclure des fichiers d'en-tête

La manière dont j'importe les fichiers d'en-tête est-elle importante? J'ai vu des guillemets doubles ainsi que des flèches utilisées.

#include <stdlib.h>
#include "Some_Header.h"

Est-ce important si elles sont capitalisées d'une certaine manière aussi? En expérimentant cela, il semble qu'aucune des deux ne soit importante, mais je suppose qu'il doit y avoir une raison pour que les tutoriels le fassent comme ils le font.

Une autre question est (venant de Java ici), comment puis-je accéder à une classe en dehors du fichier dans lequel elle a été définie? Dis, j'ai un.cpp et deux.cpp. 

Dans one.cpp:

class Something {
    ...

En deux.cpp:

class SomethingElse {
    Something *example;
    ...

Comme ça? En Java, il suffit de faire précéder le nom de la classe par "public". En C++, la discussion des classes semble être un peu plus difficile.

13
Andrew Rabon

Les crochets angulaires dans les directives #include indiquent que le chemin de recherche est limité aux répertoires d'inclusion "system". Les guillemets doubles signifient que le chemin de recherche inclut le répertoire current , suivi des répertoires inclus du système.

La casse du nom de fichier est importante lorsque votre système d'exploitation utilise un système de fichiers sensible à la casse. On dirait que vous utilisez peut-être Windows ou Mac OS X, où les noms de fichiers ne sont pas sensibles à la casse par défaut.

27
Greg Hewgill

D'abord la question simple:

Est-ce important si elles sont capitalisées d'une certaine manière aussi?

Dans la plupart des cas, includes fait référence à des fichiers et le compilateur devrait pouvoir localiser le fichier que vous incluez dans le système. Pour cette raison, la capitalisation importe dans tous les systèmes où le système de fichiers est sensible à la casse. Si vous souhaitez conserver un minimum de portabilité, vous devez être cohérent dans le nom des fichiers et dans la variable include. (Tous les linux et mac os avoir des systèmes de fichiers sensibles à la casse par défaut, dans Windows vous pouvez configurer NTFS pour qu'il soit sensible à la casse également)

Maintenant, est-ce que la façon dont le fichier est nommé importe vraiment? Non, non, tant que vous êtes cohérent dans les inclusions. Notez également qu'il est conseillé de suivre un modèle pour faciliter l'inclusion.

La manière dont j'importe les fichiers d'en-tête est-elle importante?

La norme n'est pas vraiment claire à ce stade, et différentes implémentations ont suivi des chemins différents. La norme définit qu'ils peuvent être différents, car l'ensemble des emplacements et l'ordre dans lequel le compilateur recherchera le fichier inclus sont définis par l'implémentation et peuvent différer si l'inclusion est faite avec des crochets ou des guillemets. Si l'inclusion avec des guillemets ne permet pas de localiser le fichier, le compilateur doit alors recourir à l'inclusion comme si elle avait été écrite avec des crochets.

#include <x.h> // search in order in set1 of directories
#include "x.h" // search in order in set2 of directories
               // if search fails, search also in set1

Cela implique que si un fichier n’est présent que dans set1, les deux types d’inclusions le localiseront. Si un fichier est présent dans set2 mais pas set1, seul l'inclusion de citation le localisera. Si différents fichiers portant le même nom sont présents dans set1 et set2, chaque type d'inclusion trouvera et inclura un fichier différent. Si deux fichiers portant le même nom sont présents dans les sous-ensembles communs de set1 et set2, mais que l'ordre des ensembles est différent, chaque type d'inclusion peut localiser un fichier différent.

De retour au monde réel, la plupart des compilateurs n'incluent que le répertoire en cours dans set2, set1 étant tous les emplacements d'inclusion système (qui peuvent généralement être étendus avec les arguments du compilateur). Dans ces cas, si un fichier est uniquement présent dans le répertoire en cours, #include "a.h" le localisera, mais pas #include <a.h>.

Maintenant, que ce soit le comportement commun, il existe certaines impliquées sémantiques qui sont idiomatiques en C/C++. En général, les crochets sont utilisés pour inclure les en-têtes du système et les en-têtes external , tandis que les guillemets doubles sont utilisés pour inclure local fichiers. Il existe une zone grise indiquant si une bibliothèque du même projet doit être considérée comme local ou external . C'est-à-dire que même si l'inclusion de guillemets doubles fonctionne toujours, la plupart des gens utilisent des guillemets angulaires pour faire référence à des en-têtes qui ne font pas partie du module actuel.

Enfin, bien qu'aucun compilateur que je connaisse ne le fasse, la norme permet à une implémentation (compilateur) de ne pas produire les en-têtes standard sous forme de fichiers réels, mais de traiter l'inclusion d'en-têtes standard en interne. C'est le seul cas où théoriquement #include "vector" pourrait ne pas inclure les définitions de la classe std::vector (ou de tout autre en-tête standard). Mais ce n’est pas une question pratique, et je ne pense pas que ce le sera jamais.

Les crochets angulaires recherchent l’en-tête dans les répertoires d’en-tête du système (par exemple, /usr/include). Citations est juste un chemin absolu ou relatif, tel que /path/to/header.h ou ../headers/abc.h.

Pour accéder aux classes à partir d'autres fichiers, #include l'autre fichier de la classe. Veillez à structurer votre programme de sorte qu'aucun fichier ne soit inclus plus d'une fois.

7
Delan Azabani

Question 1

La manière dont j'importe les fichiers d'en-tête A-t-elle une incidence? Est-ce que le fait qu'ils soient capitalisés Aussi importe-t-il également?

Peu importe, mais la pratique habituelle est la suivante: 

  • Utilisez des équerres pour les en-têtes du système . 
  • Guillemets utilisateur pour les en-têtes définis par l'utilisateur (Vos propres en-têtes)

Questions 2 et 3

Une autre question est (venant de Java Ici), comment puis-je accéder à une classe en dehors de Le fichier dans lequel elle a été définie?

Vous devez placer la définition de classe dans un fichier d'en-tête et inclure ce fichier d'en-tête partout où vous souhaitez utiliser la classe. Pour votre cas, cela ressemblerait à ce qui suit.

//One.h
#ifndef ONE_H
#define ONE_H
class Something
{
public:
    void doSomething(){}

};
#endif

//Two.cpp
#include "One.h"
class SomethingElse
{
   SomeThing *example;
};
7
bjskishore123

Premièrement, le #include est une directive de pré-processeur C et ne fait pas strictement partie du langage C++ en tant que tel. Vous pouvez en savoir plus à ce sujet ici bien que ceci soit spécifiquement pour le préprocesseur GNU C, il peut donc être différent de ce que vous utilisez. Je pense que vous devriez toujours assumer la casse dans les fichiers include. Ne pas le faire peut rendre difficile le portage de votre code vers un système d'exploitation sensible à la casse tel que UNIX.

L'utilisation de "" ou <> est plutôt subtile, comme expliqué ci-dessus, et la plupart du temps, vous ne remarquerez aucune différence. L'utilisation de "" recherche généralement le répertoire en cours J'ai tendance à ne pas utiliser ceci comme:

  • Je sais où sont mes en-têtes - je les spécifie toujours avec -I sur la ligne de compilation.
  • J'ai déjà été pris au dépourvu lorsqu'une copie locale d'un en-tête a annulé la copie centrale que j'espérais récupérer.

J'ai également remarqué certains effets secondaires, tels que l'utilisation de make pour créer des arbres de dépendance (je ne me souviens plus très bien du problème; les différents inclusions ont été traitées différemment, suivant certains et non d'autres, mais c'était il y a environ 7 ans.)

Deuxièmement, on répond à votre question sur la façon de référencer des fonctions dans d’autres fichiers ici /

0
Component 10