Jest to jeden z tych rodzajów „raczej” niż „powinien” standardów kodowania. Powodem jest to, że musiałbyś napisać parser C ++, aby go wymusić.
Bardzo powszechną zasadą dla plików nagłówkowych jest to, że muszą one stać same. Plik nagłówkowy nie może wymagać, aby niektóre inne pliki nagłówkowe były # zawarte przed dołączeniem danego nagłówka. Jest to wymaganie do przetestowania. Biorąc pod uwagę jakiś losowy nagłówek foo.hh
, następujące powinny się skompilować i uruchomić:
#include "foo.hh"
int main () {
return 0;
}
Ta reguła ma wpływ na użycie innych klas w niektórych nagłówkach. Czasami tych konsekwencji można uniknąć, zgłaszając dalej te inne klasy. Nie jest to możliwe w przypadku wielu standardowych klas bibliotek. Nie ma możliwości przekazania dalej deklaracji wystąpienia szablonu, takiego jak std::string
lub std::vector<SomeType>
. Musisz do #include
tych nagłówków STL w nagłówku, nawet jeśli jedynym zastosowaniem tego typu jest argument funkcji.
Innym problemem są rzeczy, które przypadkowo wciągasz. Przykład: rozważ następujące kwestie:
plik foo.cc:
#include "foo.hh"
#include "bar.hh"
void Foo::Foo () : bar() { /* body elided */ }
void Foo::do_something (int item) {
...
bar.add_item (item);
...
}
Oto bar
element Foo
danych klasy, który jest typu Bar
. Zrobiłeś to dobrze i masz #included bar.hh, chociaż musiałoby to być uwzględnione w nagłówku definiującym klasę Foo
. Nie uwzględniono jednak rzeczy używanych przez Bar::Bar()
i Bar::add_item(int)
. Istnieje wiele przypadków, w których te połączenia mogą powodować dodatkowe odniesienia zewnętrzne.
Jeśli analizujesz foo.o
za pomocą takiego narzędzia, jak nm
, okaże się, że funkcje foo.cc
wywołują wszelkiego rodzaju rzeczy, dla których nie zrobiłeś odpowiedniego #include
. Czy powinieneś zatem dodać #include
dyrektywy dotyczące tych przypadkowych odniesień zewnętrznych foo.cc
? Odpowiedź absolutnie nie jest. Problem polega na tym, że bardzo trudno jest odróżnić funkcje wywoływane przypadkowo od funkcji wywoływanych bezpośrednio.