2011-02-01 19 views
16

In che modo vengono generalmente denominate le protezioni C++? Tendo a vedere molto:Naming Includi protezioni

#ifndef FOO_H 
#define FOO_H 

// ... 

#endif 

Tuttavia, non penso che sia molto intuitivo. Senza vedere il nome del file è difficile dire a cosa serve FOO_H ea quale nome si riferisce.

Quali sono le migliori pratiche?

+2

Mentre il nome può essere più o meno intuitivo, il fatto è che con una piccola esperienza smetti di leggere quelle righe. Gli occhi e il cervello si abituano a "#ifdef blahblah ..." e praticamente non leggo quasi mai ciò che viene controllato, è una guardia di inclusione. –

+3

Un punto di vista piuttosto utile al riguardo: http://stackoverflow.com/questions/1744144/adding-an-include-guard-breaks-the-build/1744302#1744302 –

+0

Chiunque stia facendo lo sviluppo in C++ è stato meglio abituarsi a riconoscere le protezioni di intestazione molto velocemente. Seguirà SEMPRE lo standard che stai vedendo. La pratica "migliore" (tra virgolette perché è richiesta) consiste nel mettere prima ifndef, definire immediatamente dopo e terminarlo alla fine del file. Ti suggerisco di imparare a riconoscere questo al più presto. –

risposta

15

Dalla mia esperienza personale, la convenzione è denominare le protezioni di inclusione dopo il file di intestazione che li contiene con l'eccezione che il nome è tutto in maiuscolo e il punto è sostituito con un trattino basso.

Quindi test.h diventa TEST_H.

Esempi di vita reale di questo includono Qt Creator, che segue questa convenzione quando si generano automaticamente file di intestazione di classe.

+4

È utile utilizzare FILENAME_H come nome di protezione include perché si mantengono comunque tutti i file per tutti i progetti e tutte le librerie nella stessa directory senza sottodirectory, in modo da sapere che non hanno mai nomi di file in conflitto ... –

+2

Mentre questa è una pratica comune , potrebbe non essere abbastanza buono, a seconda di che altro il tuo negozio fa con #definiti e altri nomi. –

1

Normalmente uso qualcosa come FOO_H_INCLUDED_. Alcune intestazioni (Microsoft) hanno un aspetto molto simile a una rappresentazione in stringa di un GUID, ma non ho mai avuto bisogno di qualcosa di così elaborato.

3

Sostituire FOO_H con FOO_H_INCLUDED ed è più chiaro.

1

Di solito le persone lo fanno in base al nome del file in modo che il codice di ogni file venga compilato e aggiunto una sola volta. Puoi fare FOO_H come vuoi, ma quasi tutto ciò che ho codificato o visto ha usato il nome del file. Assicurati che sia unico perché non vuoi che il tuo FOO_H sia in conflitto con FOO_H di qualcun altro.

10

prese direttamente da google's style guide:

Tutti i file di intestazione dovrebbero avere #define guardie per impedire l'inclusione multipla. Il formato del nome simbolo deve essere PROJECT> _ < PERCORSO> _ < FILE> _H_. . Per garantire l'univocità di , è necessario specificare in base al percorso completo nella struttura di origine di un progetto. Ad esempio, il file foo/src/bar/baz.h nel progetto foo dovrebbe avere il seguente guardia:

#ifndef FOO_BAR_BAZ_H_ 
#define FOO_BAR_BAZ_H_ 
... 
#endif // FOO_BAR_BAZ_H_ 

Io uso questo stile nei miei progetti.

+5

Anche se in generale lo standard di codifica google è uno dei peggiori che abbia mai visto, faccio prefisso con namespace. È assolutamente necessario se hai qualcosa con gli stessi nomi in più spazi dei nomi. –

+0

Ho cercato di capire, c'è qualche ragionamento dietro il trattino basso? – Toby

+1

@Toby Solo per renderlo (più) unico ...Se qualcuno ha già un 'CONFIG_H' (come una libreria inclusa ad es.), Allora usare' CONFIG_H_' non si scontrerà con esso. La stessa ragione per cui alcune persone usano un trattino principale, ma non dovrebbero perché sono riservate. – RastaJedi

1

Io di solito guardo che ore sono e aggiungo semplicemente questo alla fine di esso, cioè FOO_H_248, è un'ulteriore precauzione, e non dovrai mai ricordarlo comunque, quindi non devi preoccuparti per il fatto che è criptico

+0

Usi l'orologio a 12 o 24 ore ed è ora locale? ;-) – T33C

+5

@ T33C: 12? 24? Di cosa stai parlando? È solo un normale orologio da 17 ore. Ed è ora locale dovunque si trovi il Papa in quel momento. –

2

Come altri hanno detto prima, una convenzione molto comune è quello di utilizzare la versione maiuscola del nome, e il punto sostituito da un carattere di sottolineatura: foo.h -> FOO_H

Tuttavia, questo può portare a conflitti di nomi con nomi semplici e/o comuni. Per questo motivo, intestazione autogenerated come stdafx.h in progetti non vuoti di Visual C++ C accoda qualche stringa casuale, come:

#ifndef FOO_H__NsknZfLkajnTFBpHIhKS 
#define FOO_H__NsknZfLkajnTFBpHIhKS 
#endif 

http://www.random.org/strings/ è un generatore casuale utile per questo.

Inoltre, se il file è parte di un modulo, o il suo contenuto risiede in uno spazio dei nomi specifici, tendo a aggiungere che alla guardia troppo:

#ifndef SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS 
#define SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS 

namespace somecomponent 
{ 
    ... 
} 

#endif 
+4

Questi sono nomi riservati, a causa della doppia sottolineatura. Quindi NON è una buona pratica usarlo. –

4

guardare il codice che # includono del vostro colpo di testa .

Se si tratta di qualcosa di simile:

#include "mylib/myheader.h" 

mylib/myheader.h è già un nome univoco. Basta capitalizzare e sostituire/e. con _

#define MYLIB_MYHEADER_H 

Se si dispone di due intestazioni sul vostro percorso di inclusione con lo stesso nome relativo al percorso includere, si dispone già di una collisione a quel livello.

16

Seguo personalmente la raccomandazione di Boost. È forse una delle più grandi raccolte di librerie C++ di buona qualità in giro e non hanno problemi.

Va come:

<project>_<path_part1>_..._<path_partN>_<file>_<extension>_INCLUDED 

// include/pet/project/file.hpp 
#ifndef PET_PROJECT_FILE_HPP_INCLUDED 

quali è:

  • legale (si noti che a partire da _[A-Z] o contenenti __ non è)
  • facile generare
  • garantiti per essere unico (come guardia inclusa) all'interno di un progetto (altrimenti hai due file nello stesso posto)
  • non garantiti da utilizzare per qualsiasi altra cosa (se si finisce un'altra macro con INCLUDED si sta rovinando per una lotta)

ho letto di GUID ma quelli guardo strano.

E ovviamente preferirei che tutti i compilatori implementare #pragma once (o meglio, #pragma multiple e "una volta" Sii il comportamento di default ...)

+0

Personalmente, sento che aggiungere l'estensione è ridondante, ma mi piace il modo in cui _INCLUDED dice effettivamente ciò che rappresenta, +1 per quello. La mia preferenza è usare INCLUDE_GUARD_FOO (senza il ridondante _H, abbiamo sempre bisogno di includere protezioni per le intestazioni, dopo tutto) che è anche un po 'più importante, ma è una questione di gusti, davvero. – cmaster

+0

@cmaster L'aggiunta di _H può essere utile in situazioni in cui si dispone di un'implementazione C e di un C++ di alcune funzionalità (utilizzando rispettivamente un file .h e un .hpp). – Squirrel