Quels sont les avantages d'un chemin relatif tel que "../include/en-tête.h " pour une tête?

j'ai passé en revue les questions comment utiliser correctement include directive et C++ #include sémantique et ni l'adresse - ni les autres suggérés par SO quand j'ai tapé le titre...

Ce que, le cas échéant, les avantages de l'écriture:

#include "../include/someheader.h"
#include "../otherdir/another.h"

comparé à l'utilisation d'un simple nom de fichier:

#include "someheader.h"
#include "another.h"

ou peut-être un nom relatif, sans le ' .. ':

#include "include/someheader.h"
#include "otherdir/another.h"

les problèmes que je vois sont:

  • vous ne pouvez pas déplacer un en-tête sans vous soucier des fichiers source qui l'incluent.
  • vous pouvez vous retrouver avec des chemins très longs pour les en-têtes dans les dépendances et les rapports d'erreurs. J'en ai eu un aujourd'hui avec ../dir1/include/../../include/../dir2/../include/header.h ".

Le seul mérite que je peux voir, c'est que si vous n'avez pas besoin de déplacer des fichiers, vous pourriez être en mesure d'obtenir loin sans toujours utiliser les directives ' -I " pour trouver les en-têtes, mais la perte de flexibilité, et la complexité de la compilation dans les sous-sous-répertoires, etc semble l'emporter sur les avantages.

alors, est-ce que je néglige un bénéfice?


Merci pour les entrées. Je pense que le consensus est qu'il n'y a pas d'avantages majeurs à l'utilisation de la notation ".."que je suis surplombant. En termes généraux, j'aime le " somewhere / header.h" la notation; je ne l'utiliser dans de nouveaux projets. Celui sur lequel je travaille est tout sauf nouveau.

l'Un des problèmes est qu'il y a divers ensembles d'en-têtes, souvent avec un préfixe tel que rspqr.h , rsabc.h , rsdef.h , rsxyz.h . Ce sont tous liés à un code dans le rsmp directory, mais certains en-têtes sont rsmp et d'autres sont dans le centre répertoire, qui n'a pas de sous-répertoires comme rsmp . (Et répétez pour les diverses autres zones du code; il y a des en-têtes à plusieurs endroits, requis au hasard par d'autres bits de code.) Déplacer des choses est un problème majeur parce que le code est devenu tellement alambiqué au fil des ans. Et les makefiles ne sont pas compatibles avec les options -I . Tout compte fait, c'est une triste histoire de négligence pas si bénigne pendant des décennies. Réparer tout ça sans rien casser va être un travail long et fastidieux.

46
demandé sur Community 2009-02-28 04:36:01

7 réponses

je préfère la syntaxe de chemin car elle rend très clair à quel namespace ou module le fichier d'en-tête appartient.

#include "Physics/Solver.h"

est très auto-Description sans exiger que chaque module préfixe leur nom aux fichiers d'en-tête.

Je n'utilise presque jamais le ".."la syntaxe cependant, à la place j'ai mon projet inclut spécifier les emplacements de base corrects.

33
répondu Andrew Grant 2009-02-28 01:42:23

le problème avec #include "../include/header.h" est qu'il fonctionne souvent par accident, et alors un changement apparemment sans rapport le fera arrêter de fonctionner plus tard.

par exemple, envisagez la disposition des sources suivante:

./include/header.h
./lib/library.c
./lib/feature/feature.c

et disons que vous exécutez le compilateur avec un chemin d'inclusion de -I. -I./lib . Ce qui se passe?

  • ./lib/library.c can do #include "../include/header.h" , ce qui a du sens.
  • ./lib/feature/feature.c peut aussi faire #include "../include/header.h" , même si cela n'a pas de sens. C'est parce que le compilateur va essayer la directive #include relative à l'emplacement du fichier courant, et si cela échoue, il va essayer la directive #include relative à chaque entrée -I dans le chemin #include .

de plus, si vous retirez plus tard -I./lib du chemin #include , alors vous cassez ./lib/feature/feature.c .

je trouve quelque chose de ce genre à être préférable:

./projectname/include/header.h
./projectname/lib/library.c
./projectname/lib/feature/feature.c

Je n'ajouterais aucune entrée de chemin include autre que -I. , et alors les deux library.c et feature.c utiliseraient #include "projectname/include/header.h" . En présumant que le" nom du projet " est probablement unique, cela ne devrait pas donner lieu à des conflits de noms ou à des ambiguïtés dans la plupart des circonstances. Vous pouvez également utiliser le chemin d'accès include et/ou la fonctionnalité VPATH de make pour diviser la disposition physique du projet. dans plusieurs répertoires si c'est absolument nécessaire (pour accommoder le code généré automatiquement par une plate-forme spécifique, par exemple; c'est quelque chose qui se décompose vraiment lorsque vous utilisez #include "../../somefile.h" ).

24
répondu bk1e 2009-02-28 03:17:37

IANALL, mais je ne pense pas que vous devriez mettre .. 's dans les fichiers source réels C ou C++, parce que ce n'est pas portable et le standard ne le supporte pas. Cela est similaire à l'utilisation de \ sur Windows. Ne le faites que si votre compilateur ne peut pas fonctionner avec une autre méthode.

9
répondu SingleNegationElimination 2015-11-24 05:33:54

pensez à votre arborescence des sources comme un espace de noms imbriqué et le chemin include vous permet de tirer des répertoires dans la racine de cet espace de noms. La question est alors de former un espace de noms logique pour votre base de code indépendamment de la façon dont le code est organisé sur le disque.

je voudrais éviter les chemins comme:

  • "include/foo/bar.h" - le" inclure "semble illogique et redondant
  • "../foo/bar.h" - le".." supposer situation relative et fragile
  • "bar.h" - sauf barre.h est dans le répertoire courant, ce qui pollue l'espace Nam global et demande des ambiguïtés.

personnellement, J'ai tendance à ajouter un chemin comme le suivant à mes projets comprennent chemin - "..;../..;../../..;../../../.." .

cela vous permet d'appliquer une sorte de règle de dissimulation à vos #include s et permet une certaine liberté de déplacer des en-têtes sans briser d'autres codes. De bien sûr, cela se fait au détriment de l'introduction d'un risque de liaison au mauvais fichier d'en-tête si vous n'êtes pas prudent car les noms non entièrement qualifiés peuvent être (ou devenir avec le temps) ambigu.

j'ai tendance à qualifier pleinement #include s dans les en - têtes publics de sorte que les tiers qui consomment mon code n'ont pas besoin d'ajouter le "..;../..;../../..;../../../.." à leur projet-c'est juste une commodité pour mon code privé et système de construction.

2
répondu Daniel Paull 2015-11-24 05:32:38

parce qu'alors vous placez le fichier relatif à la racine du projet, et quand vous le vérifiez dans le contrôle source et un autre développeur le vérifie à un endroit différent sur leur système local, les choses fonctionnent toujours.

1
répondu Joel Coehoorn 2009-02-28 01:41:25

un autre problème sur windows avec des chemins relatifs est MAX_PATH. Cela déclenchera des problèmes de compilation lorsque, par exemple, la compilation croisée pour android et votre chemin dépasse 260 de longueur.

1
répondu MadSystem 2017-10-13 15:20:41

commence le chemin de tes directives #include "" avec une séquence d'un ou plusieurs " ../ "s quand:

  • vous voulez inclure un fichier dont la colocation avec le fichier inclus est corrigée et
  • vous construisez sur un système POSIX ou avec VC++ et
  • vous souhaitez éviter toute ambiguïté sur le fichier qui sera inclus.

il est toujours facile de fournir un exemple de où votre base de code contient une erreur et où cela provoque ensuite un échec difficile à diagnostiquer. Cependant, même si votre projet n'est pas fautif, il peut être abusé par un tiers si vous utilisez des chemins absolus pour spécifier des fichiers qui sont localisés les uns par rapport aux autres.

par exemple, envisagez la mise en page suivante du projet:

./your_lib/include/foo/header1.h
./your_lib/include/bar/header2.h
./their_lib/include/bar/header2.h

Comment dois - your_lib/include/foo/header1.h inclure your_lib/include/bar / header2.h ? Considérons deux options:

  1. #include <bar/header2.h>

    en supposant que your_lib/include et your_lib/include sont cités comme des chemins de recherche d'en-tête (par exemple en utilisant les options -I ou -isystem de GCC), puis le choix de laquelle en-tête 2.h sera choisi est sensible à l'ordre dans lequel ces deux les chemins sont recherchés.

  2. #include "../bar/header2.h"

    le premier endroit dans lequel le compilateur va chercher est l'emplacement de your_lib/include/foo/header1.h , qui est your_lib/include/foo/ . Il va d'abord essayer your_lib/include/toto/../ bar / header2.h qui réduit à your_lib/include/bar/header2.h où il trouvera le de fichier correct. Les chemins de recherche des en-têtes ne seront pas utilisés du tout et il y a peu de place pour l'ambiguïté.

je recommande fortement l'option 2) dans ce cas pour les raisons données.

En réponse à certains arguments dans d'autres réponses:

  • @andrew-grant dit :

    ... il est très clair ce que l'espace de nom ou module le fichier d'en-tête appartient à.

    peut-être. Mais les chemins relatifs peuvent être interprétés comme "dans ce même module". Ils apportent une clarté dans le cas où il y a plusieurs répertoires avec le même nom situés dans des modules différents.

  • @bk1e dit :

    ...il fonctionne souvent par accident...

    les chemins relatifs ne fonctionneront que par accident dans de très rares cas où le projet a été cassé dès le début et pourrait facilement être réparé. Faire l'expérience d'une telle collision sans causer d'erreur de compilation semble peu probable. Un scénario courant est celui où le dossier d'un projet dépendant comprend l'un de vos en-têtes qui comprend un autre de vos en-têtes. La compilation de votre suite de test devrait donner lieu à une erreur "Pas de tel fichier ou répertoire" lorsqu'elle est compilée indépendamment de ce projet dépendant.

  • @singlenegationelimination dit

    ...ce n'est pas portable et la norme ne le supporte pas.

    la norme ISO C ne peut pas spécifier tous les détails des systèmes dans lesquels un programme est compilé ou exécuté. Cela ne signifie pas qu'elles ne sont pas supportées, mais simplement que la norme ne spécifie pas de manière excessive les plates-formes sur lesquelles C fonctionnera. (Le distinction entre la façon dont "" et <> sont interprétés sur la commune systèmes modernes probablement originaire dans la norme POSIX.)

  • @daniel-paull dit

    la ".."suppose une situation relative et est fragile

    Fragile comment? Probablement sensible à la colocation des deux fichiers. Ainsi " .. " ne devrait (et toujours) être utilisé lorsque l'auteur de l', y compris le fichier de contrôle de leur emplacement.

0
répondu John McFarlane 2018-09-03 06:19:56