2009-02-28 7 views
41

domande ho rivisto How to use include directive correctly e C++ #include semantics e né indirizzi questo - né gli altri suggerite da così quando ho digitato il titolo ...Quali sono i vantaggi di un percorso relativo come "../include/header.h" per un'intestazione?

cosa, se del caso, sono i vantaggi di scrittura:

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

rispetto al utilizzando solo un nome di file semplice:

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

o forse un nome relativo senza il '..':

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

I problemi che vedo sono:

  • Non è possibile spostare un colpo di testa senza preoccuparsi che i file di origine lo includono.
  • È possibile finire con percorsi molto lunghi per intestazioni nelle dipendenze e segnalazioni di errori. Ne ho avuto uno oggi con "../dir1/include/../../include/../dir2/../include/header.h".

L'unico merito che posso vedere è che, mentre non è necessario per spostare i file in giro, si potrebbe essere in grado di cavarsela senza sempre usando '-I' direttive per trovare le intestazioni, ma la perdita di flessibilità, e la la complessità della compilazione in sottodirectory, ecc. sembra superare il vantaggio.

Quindi, sto trascurando un vantaggio?


Grazie per gli input. Penso che il consenso sia che non ci sono grossi benefici alla notazione che usa ".." che sto trascurando. In termini generali, mi piace la notazione "somewhere/header.h"; Lo uso in nuovi progetti. Quello su cui sto lavorando è tutt'altro che nuovo.

Uno dei problemi è che ci sono vari tipi di intestazioni, spesso con un prefisso, come rspqr.h, rsabc.h, rsdef.h, rsxyz.h. Questi sono tutti correlati al codice nella directory rsmp, ma alcune delle intestazioni sono in rsmp e altre sono nella directory di inclusione centrale, che non ha sottodirectory come rsmp in essa. (E ripetete per le varie altre aree del codice: ci sono intestazioni in più posizioni, dovute casualmente ad altri bit di codice.) Spostare le cose è un grosso problema perché il codice è diventato così complicato nel corso degli anni. E i makefile non sono coerenti in cui sono fornite le opzioni -I. Tutto sommato, è una triste storia di negligenza non benevola su un periodo di decenni. Fissare tutto senza rompere nulla sarà un lavoro lungo e noioso.

+0

Sembra che tu sia a conoscenza di tutti i fattori coinvolti, quindi questa non è davvero una domanda. – shoosh

+0

Sto verificando se ci sono dei benefici che ho trascurato (perché odio la notazione ma ne risento al lavoro). Ho meno problemi con la notazione senza il ".." in essa. –

+0

Questo (usando percorsi relativi) tende a causare enormi mal di testa quando si utilizza una dir di compilazione separata. I.e cd yourproject; mkdir build; cd build; ../configure && make - Se hai intenzione di mantenere il codice, potrebbe valere la pena di aggiustarlo. –

risposta

28

Preferisco la sintassi del percorso in quanto rende molto chiaro a quale spazio dei nomi o modulo appartiene il file di intestazione.

#include "Physics/Solver.h" 

È molto auto-descrittivo senza richiedere a ogni modulo di anteporre il proprio nome ai file di intestazione.

Non uso quasi mai il ".."Tuttavia, la sintassi del mio progetto include specificare le posizioni di base corrette

1

Perché quindi si posiziona il file relativo alla radice del progetto e quando lo si controlla nel controllo del codice sorgente e un altro sviluppatore lo controlla in una posizione diversa sul proprio sistema locale, le cose funzionano comunque.

+3

Lo vedo come un argomento contro i nomi assoluti dei percorsi - ma non me lo chiedevo (sono inequivocabilmente cattivi AFAIAC). Non sono convinto che questo sia un argomento per - o contro - nessuna delle varianti del nome relativo. –

2

Pensa al tuo albero dei sorgenti come uno spazio dei nomi annidato e il percorso di inclusione ti consente di inserire le directory nella radice di questo spazio dei nomi. uno di formare uno spazio dei nomi logico per la vostra base di codice a prescindere dal modo in cui il codice è organizzato su disco

vorrei evitare percorsi come:.

  • "include/foo/bar.h" - la "include" sembra illogico e ridondanti
  • "../foo/bar.h"- il ".." assume posizione relativa ed è fragile
  • "bar.h" - a meno che bar.h non sia nella directory corrente, questo inquina lo spazio dei nomi globale e richiede ambiguità.

Personalmente, io tendo ad aggiungere un percorso simile al seguente per i miei progetti include percorso - "..;../..;../../..;../../../..".

Ciò consente di applicare una sorta di regola di mascheramento al proprio #include e consente una certa libertà di spostare le intestazioni senza interrompere altri codici. Naturalmente questo è a scapito dell'introduzione del rischio di associazione al file di intestazione errato se non si presta attenzione poiché i nomi non pienamente qualificati possono essere (o diventare col tempo) ambigui.

Io tendo a qualificare completamente #include s nelle intestazioni pubbliche in modo che le terze parti che consumano il mio codice non debbano aggiungere il "..;../..;../../..;../../../.." al loro progetto - è solo una comodità per il mio codice privato e sistema di compilazione.

+1

Qual è lo scopo di ';' nel tuo percorso? – Royi

+1

Il ";" è un separatore di percorsi in Windows, in particolare, è come si fornisce un set di directory per cercare in Visual Studio. –

+0

Potresti elaborare. Non sono sicuro di aver capito. Grazie. – Royi

8

IANALL, ma non penso che dovresti inserire lo .. in veri e propri file sorgente C o C++, perché non è portatile e lo standard non lo supporta. Questo è simile all'utilizzo di \ su Windows. Fallo solo se il tuo compilatore non può funzionare con nessun altro metodo.

+3

Buon punto. Lo standard non sembra nemmeno garantire che sia possibile utilizzare le barre di avanzamento. "L'implementazione fornisce mappature univoche per sequenze composte da uno o più non condittrici (lex.name) seguiti da un punto (.) E da un singolo nondigit." Definisce nondigit come fondamentalmente [_a-zA-Z] o \ uNNNN. – bk1e

+0

Questo è vero, ma il software in questione è stato compilato su una vasta gamma di piattaforme per un numero di anni (più di venti), quindi è più una responsabilità teorica che pratica. –

+1

Zero hit di Google per IANALL. Presumo che sia "Non sono un avvocato linguistico"? –

22

Il problema con #include "../include/header.h" è che spesso funziona per sbaglio, e quindi un cambiamento apparentemente non correlato lo farà smettere di funzionare più tardi.

Ad esempio, si consideri il seguente schema fonte:

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

E diciamo che si sta eseguendo il compilatore con un percorso di includere -I. -I./lib. Che succede?

  • ./lib/library.c può fare #include "../include/header.h", che ha senso.
  • ./lib/feature/feature.c può anche fare #include "../include/header.h", anche se non ha senso. Questo perché il compilatore proverà la direttiva #include relativa alla posizione del file corrente e, se fallisce, proverà la direttiva #include relativa a ciascuna voce -I nel percorso #include.

Inoltre, se toglierete -I./lib dal percorso #include, allora si rompe ./lib/feature/feature.c.

trovo qualcosa come la seguente preferibile:

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

non vorrei aggiungere alcun percorso di inclusione voci diverse da -I., e poi entrambi library.c e feature.c userei #include "projectname/include/header.h". Supponendo che "projectname" sia probabilmente unico, questo non dovrebbe comportare collisioni di nomi o ambiguità nella maggior parte delle circostanze. È inoltre possibile utilizzare la funzione include path e/o make VPATH per dividere il layout fisico del progetto su più directory se assolutamente necessario (per adattare codice generato automaticamente specifico della piattaforma, ad esempio, si tratta di qualcosa che si interrompe davvero quando si utilizza #include "../../somefile.h").

+1

sì quella cosa che usa "projectname/include/header.h" era ciò che usavo nel mio ultimo progetto (ma partivo da include/invece). ne metto sempre solo uno -I che punta al percorso/includi e poi includo in base a ciò. ma non ho ancora analizzato i ".." problemi in profondità. Hai dei buoni punti. –

1

Un altro problema su Windows con percorsi relativi è MAX_PATH. Ciò attiverà problemi di compilazione quando ad es. cross-compilation per Android e il tuo percorso cresce più di 260 di lunghezza.

Problemi correlati