2011-02-01 16 views
16

W jaki sposób C++ obejmuje typowe nazwy strażników? Często widzę to:Nazewnictwo obejmuje strażników

#ifndef FOO_H 
#define FOO_H 

// ... 

#endif 

Jednak nie sądzę, że jest to bardzo intuicyjne. Bez wyświetlania nazwy pliku trudno jest określić, co jest potrzebne i do czego odnosi się nazwa.

Co jest uważane za najlepszą praktykę?

+2

Choć nazwa może być mniej lub bardziej intuicyjny, faktem jest, że z trochę doświadczenia, przestań czytać te linie. Oczy i mózgi przyzwyczajają się do '#ifdef blahblah ...' i prawie nigdy nie czytam tego, co jest sprawdzane, to jest strażnik. –

+3

Nieco przydatny punkt widzenia na ten temat: http://stackoverflow.com/questions/1744144/adding-an-include-guard-breaks-the-build/1744302#1744302 –

+0

Każdy, kto zajmuje się rozwojem C++, lepiej przyzwyczaja się do rozpoznawania osłon nagłówka bardzo szybko. ZAWSZE będzie podążał za standardem, który widzisz. "Najlepsza" praktyka (w cudzysłowie, ponieważ jest to wymagane) polega na umieszczeniu najpierw ifndef, zdefiniowaniu zaraz po, i zakończeniu na końcu pliku. Sugeruję, abyś nauczył się rozpoznawać to jak najszybciej. –

Odpowiedz

15

Z własnego doświadczenia wynika, że ​​konwencja ma nazywać strażników umieszczenia po pliku nagłówkowym, który je zawiera, z wyjątkiem tego, że nazwa jest w literach, a kropka jest zastąpiona znakiem podkreślenia.

Tak test.h staje się TEST_H.

Przykładami tego są Qt Creator, który stosuje się do tej konwencji podczas automatycznego generowania plików nagłówkowych klas.

+4

Dobrze jest użyć pliku FILENAME_H jako nazwy strażnika, ponieważ zachowujesz wszystkie pliki dla wszystkich projektów i wszystkich bibliotek w tym samym katalogu bez żadnych podkatalogów, więc wiesz, że nigdy nie mają konfliktowych nazw plików ... –

+2

Chociaż jest to powszechna praktyka , może nie być wystarczająco dobre, w zależności od tego, co jeszcze robi twój sklep z # definicjami i innymi nazwami. –

1

Zwykle używam czegoś takiego jak FOO_H_INCLUDED_. Kilka nagłówków (Microsoft) ma coś, co wygląda jak ciąg znaków GUID, ale ja nigdy nie potrzebowałem niczego tak wyszukanego.

3

Wymień FOO_H na FOO_H_INCLUDED i jest jaśniejszy.

1

Zwykle ludzie robią to według nazwy pliku, aby każdy kod pliku został skompilowany i dodany tylko raz. Możesz zrobić FOO_H, co chcesz, ale prawie wszystko, co kiedykolwiek napisałem lub widziałem, używało nazwy pliku. Upewnij się, że jest wyjątkowy, ponieważ nie chcesz, aby FOO_H kolidował z czyimś FOO_H.

10

pobierane bezpośrednio z google's style guide:

Wszystkie pliki nagłówkowe powinny mieć #define osłony zapobiegające wielokrotnej integracji. Format nazwy symbolu powinien być be < PROJEKT> _ < ŚCIEŻKA> _ < PLIK> _H_. Aby uzyskać unikalność , powinny one być oparte na pełnej ścieżce w drzewie źródłowym projektu . Na przykład, plik foo/src/bar/baz.h w projekcie foo powinna mieć następujące Strażnik:

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

używam tego stylu w moich własnych projektów.

+5

Chociaż ogólnie rzecz biorąc standard google jest jednym z gorszych, jakie kiedykolwiek widziałem, robię przedrostek z przestrzenią nazw. Jest absolutnie konieczne, jeśli masz coś o tych samych nazwach w wielu przestrzeniach nazw. –

+0

Próbowałem dowiedzieć się, czy istnieje jakieś rozumowanie za końcowym podkreśleniem? – Toby

+1

@Toby Tylko po to, aby była (bardziej) wyjątkowa ...Jeśli ktoś ma już 'CONFIG_H' (jak np. Dołączona biblioteka np.), Użycie' CONFIG_H_' nie będzie z nim sprzeczne. Z tego samego powodu niektórzy ludzie używają wiodącego podkreślenia, ale nie powinni tego robić, ponieważ rezerwy są zastrzeżone. – RastaJedi

1

Zwykle patrzę, która jest godzina i po prostu dołączam ją do końca, tj. FOO_H_248, jest to dodatkowy środek ostrożności, i nigdy nie będziesz musiał tego pamiętać, więc nie musisz się martwić Fakt, że jest tajemniczy.

+0

Czy używasz zegara 12- lub 24-godzinnego i czy jest to czas lokalny? ;-) – T33C

+5

@ T33C: 12? 24? O czym mówisz? To tylko zwykły zegar 17-godzinny. I jest czas lokalny do miejsca, w którym Papież jest w tym momencie. –

2

Jak inni wspomniano wcześniej, to bardzo powszechne konwencja jest użycie wielkiej litery wersję nazwy, a kropkę zastąpiono podkreślenia: Foo.h -> FOO_H

Jednakże, może to prowadzić do kolizji z nazwy proste i/lub popularne nazwy. Z tego powodu, wygenerowany automatycznie nagłówek jak stdafx.h w niepustymi Visual C++ C projektów dołączyć jakiś losowy ciąg znaków, takich jak:

#ifndef FOO_H__NsknZfLkajnTFBpHIhKS 
#define FOO_H__NsknZfLkajnTFBpHIhKS 
#endif 

http://www.random.org/strings/ jest przydatny generator liczb losowych za to.

Ponadto, jeśli plik jest częścią jakiegoś modułem lub jej zawartość znajdują się w jednej konkretnej przestrzeni nazw, staram się dodać, że na straży TOO:

#ifndef SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS 
#define SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS 

namespace somecomponent 
{ 
    ... 
} 

#endif 
+4

Są to zastrzeżone nazwy z powodu podwójnego podkreślenia. NIE jest więc dobrą praktyką. –

4

spojrzeć na kod, który #include za swój nagłówek .

Jeśli jest coś takiego:

#include "mylib/myheader.h" 

mylib/myheader.h jest już unikalną nazwę. Po prostu zamień na wielką i zastąp/i. z _

#define MYLIB_MYHEADER_H 

Jeśli masz dwa nagłówki na własną zawierać ścieżkę o takiej samej nazwie w stosunku do ścieżki obejmują, masz już kolizji na tym poziomie.

16

Osobiście postępuję zgodnie z zaleceniem Boost. Jest to prawdopodobnie jedna z największych kolekcji dobrych bibliotek C++ i nie mają problemu.

To idzie tak:

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

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

który jest:

  • prawny (zauważ, że rozpoczęcie przez _[A-Z] lub zawierające __ nie jest)
  • łatwy do wygenerowania
  • gwarancją wyjątkowy (jako strażnik) w ramach projektu (w przeciwnym razie masz dwa pliki w tym samym miejscu)
  • nie gwarantuje być używana do niczego innego (jeśli kończy kolejne makro z INCLUDED jesteś psucie się do walki)

Czytałem o GUID ale te wyglądają dziwnie.

I oczywiście wolałbym niż wszystkie kompilatory wdrożyć #pragma once (lub lepiej, #pragma multiple i „po” jest domyślne zachowanie ...)

+0

Osobiście uważam, że dodanie rozszerzenia jest zbędne, ale podoba mi się sposób, w jaki _INCLUDED mówi co to oznacza, +1 za to. Preferuję użycie INCLUDE_GUARD_FOO (bez zbędnego _H, w końcu potrzebujemy tylko osłony do nagłówków), co jest nawet trochę bardziej do rzeczy imho, ale to jest kwestia gustu, naprawdę. – cmaster

+0

@cmaster Dodanie _H może być pomocne w sytuacjach, w których masz implementację niektórych funkcji C i C++ (przy użyciu odpowiednio plików .h i .hpp). – Squirrel