2010-12-10 20 views
26

¿Por qué se importa el mapa como #include <map>, pero stdio se importó como #include <stdio.h>?¿Por qué algunos incluyen necesitan el .h y otros no?

+2

stdio también se pueden importar como '' # include mkb

+0

@ Matt: Así que el nombre de importación es diferente del nombre de archivo. ¿Cómo se hace eso? – Casebash

+0

@Casebach: usualmente hay dos archivos separados, 'cstdio' y' stdio.h', con 'cstdio' incluyendo' stdio.h' de una manera que pone todos sus símbolos en el espacio de nombres std. Pero la forma exacta en que lo hace depende de la implementación. –

Respuesta

27

Todos los encabezados estándar de C++ no quieren el .h al final. Leí en alguna parte que el concepto es que ellos no tienen que ser archivos reales, aunque nunca vi una implementación hacerlo de otra manerade edición: en realidad las características intrínsecas del compilador debe trabajar teniendo en cuenta las cabeceras incluidas, pero no incluirlos como archivos; ver @Yttrill del comentario.

Para la cosa stdio.h, en una aplicación C++ no debe incluir <stdio.h>, pero en su lugar debe incluir <cstdio>. En general, no debe incluir los encabezados C "normales", pero sus contrapartes C++ --ized, que no tienen el .h al final, tienen un c al frente y ponen todos los símbolos definidos en ellos en el std espacio de nombres. Por lo tanto, <math.h> se convierte en <cmath>, <stdlib.h> se convierte en <cstdlib>, y así sucesivamente.

En general, debe usar las versiones en C++ de los encabezados C para evitar contaminar el espacio de nombres global (suponiendo que no sea uno de esos tipos que ponen using namespace std; en todas partes) y para beneficiarse de algunas mejoras de C++ en el cabezales C estándar (p. ej., sobrecarga añadida a algunas funciones matemáticas).


En general, la implementación de todo esto se hace simplemente teniendo tales archivos sin extensión en el directorio en el que el compilador busca los archivos de encabezado. En mi g ++ 4.4 instalación, por ejemplo, usted tiene:

[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 

El C++ - Ized cabeceras C en teoría podría ser sólo una

namespace std 
{ 
#include <original_C_header.h> 
}; 

pero en general son más complicados para hacer frente a la aplicación específica problemas (especialmente con respecto a las macros) y para agregar funcionalidad relacionada con C++ (véase, por ejemplo, el ejemplo anterior de sobrecargas añadidas en <cmath>).


Por cierto, el estándar de C++ (§D.5) no dicen que los <c***> cabeceras deben comportarse como si se incluyen las cabeceras <***.h> en una directiva namespace std, sino todo lo contrario:

Para compatibilidad con la biblioteca estándar C, la biblioteca estándar de C++ proporciona los encabezados [...] 18 C Cada encabezado C, cuyo nombre tiene el nombre de forma.h, se comporta como si cada nombre colocado en el espacio de nombres de la biblioteca estándar por el correspondiente El encabezado cname también se coloca dentro del ámbito del espacio de nombres del espacio-nombre std y va seguido de una declaración explícita de uso (7.3.3)

Tenga en cuenta que este tipo de cabeceras se consideran obsoleta (§C.2.1), por lo que esta es la razón principal por la que no debería usarlos:

C.2.1 Las modificaciones a las cabeceras de Para la compatibilidad con la biblioteca Standard C, la biblioteca estándar de C++ proporciona los 18 encabezados C (D.5), pero su uso está en desuso en C++.

+5

Dado que Matteo en realidad no proporcionó ningún motivo para usar las versiones C++ de los encabezados estándar C, daré uno: Los encabezados C++ a menudo proporcionan versiones sobrecargadas de las funciones de biblioteca estándar C, que están optimizadas para el tipo de datos real de los argumentos. C también proporciona estas versiones múltiples, pero todas tienen diferentes nombres (por ejemplo, 'abs' vs' fabs' contra 'fabs' contra' fabsl'). Hace una diferencia con '#include ' si está usando plantillas, y no tanto o para otros encabezados. –

+0

@Ben Voigt: curiosamente, lo agregué de forma independiente en la última revisión (después de echar un rápido vistazo al archivo 'cmath') :) –

+1

contaminación del espacio de nombres no es en realidad una razón para usar la versión C++ de los encabezados, ya que nadie en su sano juicio usaría nombres que entren en conflicto con la biblioteca estándar de C –

2

Es simplemente el nombre del archivo real en el disco. No hay (probablemente) ningún archivo llamado map.h o stdio en su directorio de inclusión estándar.

La biblioteca estándar de C++ se alejó del estilo anterior de usar .h para no tener .h al final de los nombres de archivo. Esto puede posiblemente se han relacionado con lo que la sintaxis se parecen más a las plantillas:

#include<vector> 

vector<int> v; 

(comentario preventiva:. Sí, sé que las necesidades anteriores std:: para construir, pero es sólo un ejemplo)

+0

No quiero rechazar una respuesta de la competencia, pero esto es realmente inexacto: no hay garantía de que los archivos 'map' o' stdio.h' existan en el disco. –

+0

Eso es cierto, no hay garantía. Sin embargo, la mayoría de los compiladores almacenan los encabezados de las bibliotecas estándar como archivos en el disco; sin duda, los populares comúnmente disponibles. –

+0

Claro, esa es la opción de implementación obvia. No renuncié, solo quería observar que "es simplemente el nombre del archivo real en el disco" no es estrictamente exacto en lo que respecta al estándar. –

2

Es solo la forma en que está definido por el estándar C++: como ocurre, map y stdio.h ni siquiera tienen que ser archivos reales.

Como nota al margen, stdio.h es el encabezado que se importó originalmente a C++ desde las bibliotecas estándar de C: la versión de C++ es cstdio. En términos prácticos, esto generalmente significa que cuando incluye cstdio, obtiene el material de stdio.h, pero está en el espacio de nombres estándar.

Solo para aclarar: el stdio.h que incluye en C++ es la versión en C++ de lo que originalmente era un encabezado en C. Pero la forma C++ de escribir el include es cstdio.

+1

No, '#include ' en un programa C++ no le da la versión de las bibliotecas estándar C (o de todos modos no se supone que así sea), vea http://stackoverflow.com/questions/4405887/when-the- c-standard-provides-c-headers-bringing-names-to-the-global-namespace –

+0

@Ben: De hecho, expresé esto incorrectamente, quise decir que es la forma de escribir estilos C-C++, y no pone cosas en namespace std. –

Cuestiones relacionadas