2010-10-15 22 views
10

Dopiero co zauważyłem, że moje programy używające klasy ciągów kompilowały się bez nagłówka <string>. Okazuje się, że <iostream> obejmuje <ios_base>, która z kolei obejmuje <string>.powinienem dołączyć nagłówek, który jest już zawarty w innych nagłówkach?

Czy to jest zła praktyka i czy powinienem wyraźnie zawrzeć <string>? Nawet jeśli to tylko kwestia jasności?

Czy można bezpiecznie założyć, że dotyczy to nie tylko nagłówka <string>? Być może jest to implementacja specyficzna i czy standard podaje nagłówek <string> za pośrednictwem <ios_base> i <iostream>? Zapewnienie, że każda szanowana i szeroko stosowana implementacja zawsze będzie zawierała <string>, pod warunkiem, że istnieje połączenie z <iostream>.

+2

http://en.wikipedia.org/wiki/Incl ude_guard. Standardowa biblioteka je posiada. – Dragontamer5788

+0

To całkiem wygodne, ponieważ nie zostałem wprowadzony do tej funkcji. Dzięki. – aLostMonkey

Odpowiedz

10

Należy jawnie dołączyć wszelkie standardowe nagłówki biblioteki, których potrzebujesz.

Nie określono, które standardowe nagłówki bibliotek znajdują się w innych standardowych nagłówkach bibliotek, więc takie szczegóły będą się różnić między kompilatorami.

Jeden przypadek, w którym można polegać na nagłówku dołączonym przez inny nagłówek jest, jeśli klasa w jednym nagłówku pochodzi z klasy w innym. Na przykład <iostream> musi zawierać <ios_base>, ponieważ klasy zdefiniowane w <iostream> pochodzą z klas zdefiniowanych w <ios_base>.

+2

Każdy, kto przeniesie aplikację do innego systemu operacyjnego lub zaktualizuje aplikację do kompilacji za pomocą innego kompilatora, podziękuje Ci, jeśli postąpisz zgodnie z radą Jamesa McNellisa w tej sprawie. Uwierzcie mi, musiałem napisać kilka złośliwych e-maili w zeszłym tygodniu z powodu ludzi nie wliczając odpowiednich nagłówków. Kilka innych ważnych: memset nie znajduje się w memory.h, to nietypowy Microsoftism. Inny przykład: fabs i abs są w stdlib.h, nie math.h. – George

+3

@George: 'fabs' jest w' '. 'abs' dla formalnego argumentu typu integralnego jest w' ', podczas gdy' abs' dla argumentu zmiennoprzecinkowego (w C++, ale myślę, że nie w C) jest w ''. Cheers & hth., –

+0

@Alf P. Steinbach: Masz rację co do fabs, oops. abs jest przeciążony tylko dla C++.Ponieważ kompilowaliśmy ten sam kod z kompilatorem C zamiast kompilatorem C++, musiałem pójść i zamienić kilka połączeń abs() z fabs(). To właśnie dostaję do wysyłania, kiedy nie mam kofeiny. :) – George

7

Dobrą praktyką jest zawsze zawierać nagłówki klas, z których będziesz korzystać w danym pliku źródłowym, niezależnie od tego, czy "wiesz", że są zawarte w już dołączonych plikach.

Jeśli podczas refaktoryzacji kodu usuniesz konieczność dołączenia jednego z plików na wyższym poziomie (na przykład iostream), ustalenie, dlaczego aplikacja nie jest już kompilowana, może być dość bolesne.

+3

+1 Ściskacie przycisk "Wyślij" na 2 sekundy przed moim prawie od słowa w słowo. – Anthony

+0

Jeśli chcesz, aby twoje zależności makefile były dokładne, to w tym nagłówku jest * MUST * a nie * SHOULD *. – jww

2

Jeśli dodasz odpowiedni nagłówek (z "#pragma raz" lub właściwym #ifndef) więcej niż jeden raz, to tylko trochę więcej czasu na kompilowanie (tylko po to, aby otworzyć, przeanalizować i ukryć zawartość pliku nagłówkowego) , ale nic nie jest zbyt poważne, ponieważ sprawia, że ​​twoje pliki są łatwiejsze do skompilowania, jeśli okoliczności się zmienią (tj. przenieś je do innego projektu, utwórz z nich bibliotekę itp.) Jeśli naprawdę martwisz się o czas kompilacji dodaj to samo # IFNDEF przed tym nagłówek (choć nie jest to zalecane)

tj

// header.h 
#ifndef _HEADER_H 
#define _HEADER_H 
int blahblahblah(int); 
#endif 


// cppfile.cpp 
#ifndef _HEADER_H 
#include <header.h> 
#endif 
Powiązane problemy