Почему карта импортируется как #include <map>
, но stdio импортируется как #include <stdio.h>
?
Почему некоторые из них нуждаются в .h, а другие нет?
Ответ 1
Все стандартные заголовки С++ не хотят .h
в конце. Я где-то читал, что концепция состоит в том, что им не нужны фактические файлы, , даже если я никогда не видел реализацию, сделав это другим способом edit: на самом деле внутренняя среда компилятора должна работать с учетом включенных заголовков, но фактически не включать их в качестве файлов; см. комментарий @Yttrill.
Для объекта stdio.h
в приложении С++ вы не должны включать <stdio.h>
, но вместо этого вы должны включить <cstdio>
. В общем случае вы не должны включать "нормальные" заголовки C, но их С++-азизированные копии, у которых в конце концов нет .h
, имеют перед собой c
и помещают все символы, определенные в них в пространстве имен std
. Итак, <math.h>
становится <cmath>
, <stdlib.h>
становится <cstdlib>
и т.д.
В общем, вы должны использовать С++-версии версий заголовков C, чтобы избежать загрязнения глобального пространства имен (при условии, что вы не один из тех парней, которые поместили using namespace std;
всюду), и чтобы воспользоваться некоторыми улучшениями на С++ для стандартные заголовки C (например, добавлена перегрузка к некоторым математическим функциям).
В общем, реализация всего этого просто делается путем наличия таких файлов без расширения в каталоге, в котором компилятор ищет файлы заголовков. Например, в моей установке g++ 4.4 у вас есть:
[email protected]:/usr/include/c++/4.4$ ls
algorithm cstdarg functional sstream
array cstdatomic initializer_list stack
backward cstdbool iomanip stdatomic.h
bits cstddef ios stdexcept
bitset cstdint iosfwd streambuf
c++0x_warning.h cstdio iostream string
cassert cstdlib istream system_error
ccomplex cstring iterator tgmath.h
cctype ctgmath limits thread
cerrno ctime list tr1
cfenv cwchar locale tr1_impl
cfloat cwctype map tuple
chrono cxxabi-forced.h memory typeinfo
cinttypes cxxabi.h mutex type_traits
ciso646 debug new unordered_map
climits deque numeric unordered_set
clocale exception ostream utility
cmath exception_defines.h parallel valarray
complex exception_ptr.h queue vector
complex.h ext random x86_64-linux-gnu
condition_variable fenv.h ratio
csetjmp forward_list regex
csignal fstream set
С++-ized C заголовки в теории могут быть просто
namespace std
{
#include <original_C_header.h>
};
но в целом они сложнее решать специфические для реализации проблемы (особенно в отношении макросов) и добавлять связанные с С++ функциональные возможности (см., например, предыдущий пример добавленных перегрузок в <cmath>
).
Кстати, стандарт С++ (§D.5) не говорит, что заголовки
<c***>
должны вести себя так, как если бы они включали заголовки <***.h>
в директиве namespace std
, но наоборот:
Для совместимости со стандартной библиотекой C библиотека Standard С++ предоставляет заголовки 18 C [...] Каждый заголовок C, имя которого имеет форму name.h, ведет себя так, как если бы каждое имя, помещенное в пространство имен стандартной библиотеки соответствующим заголовком cname, также помещалось в область пространства имен пространства имен std и сопровождалось явным использованием- декларация (7.3.3)
Обратите внимание, что такие заголовки считаются устаревшими (§С .2.1), поэтому это основная причина, по которой вы не должны их использовать:
C.2.1 Изменения заголовковДля совместимости со стандартной библиотекой C библиотека Standard С++ предоставляет заголовки 18 C (D.5), но их использование устарело в С++.
Ответ 2
Это просто имя фактического файла на диске. В вашем стандартном каталоге include (возможно) нет файла с именем map.h
или stdio
.
Стандартная библиотека С++ отошла от предыдущего стиля использования .h
к отсутствию .h
в конце имен файлов. Возможно, это связано с тем, что синтаксис больше похож на шаблоны:
#include<vector>
vector<int> v;
(Упреждающий комментарий: Да, я знаю, что это нужно для создания std::
, но это всего лишь иллюстрация.)
Ответ 3
Это так, как он определен стандартом С++ - как это бывает, map
и stdio.h
даже не должны быть реальными файлами.
Как примечание, stdio.h
- это заголовок, который был первоначально импортирован в С++ из стандартных библиотек C - версия С++ cstdio
. С практической точки зрения это обычно означает, что при включении cstdio
вы получаете материал из stdio.h
, но в пространстве имен std.
Просто пояснить: stdio.h
, который вы включаете в С++, является версией С++ того, что первоначально было заголовком C. Но С++ способ записи include - cstdio
.