* .h o * .hpp para sus definiciones de clase


555

Siempre he usado un *.harchivo para mis definiciones de clase, pero después de leer un código de biblioteca de impulso, me di cuenta de que todos lo usan *.hpp. Siempre tuve una aversión a esa extensión de archivo, creo que principalmente porque no estoy acostumbrado.

¿Cuáles son las ventajas y desventajas de usar *.hppmás *.h?

Respuestas:


528

Aquí hay un par de razones para tener diferentes nombres de encabezados C vs C ++:

  • Formateo automático de código, puede tener diferentes pautas para formatear el código C y C ++. Si los encabezados están separados por extensión, puede configurar su editor para que aplique el formato apropiado automáticamente
  • Nombrando, he estado en proyectos donde había bibliotecas escritas en C y luego se habían implementado contenedores en C ++. Como los encabezados generalmente tenían nombres similares, es decir, Feature.h vs Feature.hpp, eran fáciles de distinguir.
  • Inclusión, tal vez su proyecto tenga versiones más apropiadas disponibles escritas en C ++, pero está utilizando la versión C (consulte el punto anterior). Si los encabezados se nombran después del lenguaje en el que se implementan, puede detectar fácilmente todos los encabezados C y buscar versiones de C ++.

Recuerde, C no es C ++ y puede ser muy peligroso mezclar y combinar a menos que sepa lo que está haciendo. Nombrar sus fuentes apropiadamente lo ayuda a distinguir los idiomas.


234

Uso .hpp porque quiero que el usuario diferencie qué encabezados son encabezados de C ++ y qué encabezados son encabezados de C.

Esto puede ser importante cuando su proyecto usa módulos C y C ++: como alguien más me explicó antes, debe hacerlo con mucho cuidado, y comienza con el "contrato" que ofrece a través de la extensión

.hpp: encabezados C ++

(O .hxx, o .hh, o lo que sea)

Este encabezado es solo para C ++.

Si está en un módulo C, ni siquiera intente incluirlo. No le gustará, porque no se hace ningún esfuerzo para hacerlo compatible con C (se perdería demasiado, como sobrecarga de funciones, espacios de nombres, etc., etc.).

.h: Encabezados C / C ++ compatibles o C puros

Este encabezado puede ser incluido por una fuente C y una fuente C ++, directa o indirectamente.

Se puede incluir directamente, estando protegido por la __cplusplusmacro:

  • Lo que significa que, desde el punto de vista de C ++, el código compatible con C se definirá como extern "C".
  • Desde el punto de vista de C, todo el código de C será claramente visible, pero el código de C ++ estará oculto (porque no se compilará en un compilador de C).

Por ejemplo:

#ifndef MY_HEADER_H
#define MY_HEADER_H

   #ifdef __cplusplus
      extern "C"
      {
   #endif

   void myCFunction() ;

   #ifdef __cplusplus
      } // extern "C"
   #endif

#endif // MY_HEADER_H

O podría incluirse indirectamente por el encabezado .hpp correspondiente que lo incluye con la extern "C"declaración.

Por ejemplo:

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP

extern "C"
{
#include "my_header.h"
}

#endif // MY_HEADER_HPP

y:

#ifndef MY_HEADER_H
#define MY_HEADER_H

void myCFunction() ;

#endif // MY_HEADER_H

3
Esto es poco habitual en muchos proyectos de C ++. Los archivos .h se usan para cosas que no son muy atractivas.
einpoklum

44
@einpoklum: Por supuesto. Pero trato de evitar el comportamiento "Monkey See Monkey Do". En el caso actual, ambas extensiones (y otras) están disponibles, así que trato de hacer que realmente cuenten. Tener este contrato con el código que se comparte con los clientes es muy útil: todos (es decir, cientos de desarrolladores) saben que los clientes deben usar los archivos ".H" utilizando un compilador de C, por lo que no hay dudas sobre lo que puede llegar allí o no. Y todos (incluidos los clientes) saben que los archivos ".HPP" nunca intentarán ser compatibles con C. Todos ganan.
paercebal

44
@paercebal, entonces ¿estás sugiriendo .H en lugar de .h , y .HPP sobre .hpp ?
Geof Sawaya

66
@ GeofSawaya: No, lo siento. Es un habito. Cuando escribo artículos, uso extensiones en mayúsculas para diferenciar los archivos por su tipo, como "archivos .HPP". Pero las extensiones de los archivos reales que están en mi disco duro siempre están en minúsculas, incluso en el nombre no, como "MyClass.hpp" o "module.hpp"
paercebal

44
Gracias, @paercebal. Me estaba poniendo pedante
Geof Sawaya

48

Siempre consideré que el .hppencabezado era una especie de acrónimo .hy de .cpparchivos ... un encabezado que también contiene detalles de implementación.

Típicamente cuando he visto (y uso) .hpp como una extensión, no hay un .cpparchivo correspondiente . Como han dicho otros, esta no es una regla difícil y rápida, solo cómo tiendo a usar .hpparchivos.


31

No importa qué extensión uses. Cualquiera de los dos está bien.

Yo uso *.hpara C y *.hpppara C ++.


23

EDITAR [Sugerencia agregada de Dan Nissenbaum]:

Por una convención, los archivos .hpp se usan cuando los prototipos se definen en el encabezado mismo. Dichas definiciones en los encabezados son útiles en el caso de las plantillas, ya que el compilador genera el código para cada tipo solo en la creación de instancias de plantilla. Por lo tanto, si no se definen en archivos de encabezado, sus definiciones no se resolverán en el momento del enlace desde otras unidades de compilación. Si su proyecto es un proyecto solo en C ++ que hace un uso intensivo de plantillas, esta convención será útil.

Ciertas bibliotecas de plantillas que se adhieren a esta convención proporcionan encabezados con extensiones .hpp para indicar que no tienen los archivos .cpp correspondientes.

otra convención es usar .h para encabezados C y .hpp para C ++; Un buen ejemplo sería la biblioteca de impulso.

Cita de Boost FAQ,

Las extensiones de archivo comunican el "tipo" del archivo, tanto a los humanos como a los programas de computadora. La extensión '.h' se usa para archivos de encabezado C y, por lo tanto, comunica lo incorrecto sobre los archivos de encabezado C ++. El uso de ninguna extensión no comunica nada y fuerza la inspección del contenido del archivo para determinar el tipo. El uso de '.hpp' lo identifica inequívocamente como un archivo de encabezado C ++ y funciona bien en la práctica real. (Rainer Deyke)


Nada de eso es cierto, no importa si el archivo es .h o .hpp cuando se trata de generar o vincular código.
Mark Ingram

¿No es solo una cuestión de convención? La biblioteca estándar de C ++ proporciona todos sus encabezados sin ninguna extensión. el uso de ".hpp" solo indica que los prototipos están definidos en el mismo archivo y no habrá ningún archivo .cpp correspondiente.
ProgramCpp

55
Creo que esta respuesta es útil, con la excepción de que le falta una frase muy simple pero importante: "por convención, no por las reglas del lenguaje" (en alguna parte).
Dan Nissenbaum

13

Recientemente comencé a usar *.hpp para encabezados c ++.

La razón es que uso emacs como mi editor principal y entra automáticamente en modo c cuando carga un *.harchivo y en modo c ++ cuando carga un *.hpparchivo.

Aparte el hecho de ver que no hay buenas razones para elegir *.hmás *.hppo viceversa.


77
Personalmente, creo que resaltar C ++ es una buena idea incluso en los encabezados C. He estado en ambos extremos de la situación en la que alguien quiere incluir su encabezado C de C ++, pero usa una palabra clave C ++ como nombre de parámetro ...
Steve Jessop

12

Estoy respondiendo esto como un recordatorio, para dar un punto a mi comentario (s) sobre la respuesta "user1949346" a este mismo OP.


Entonces, como muchos ya respondieron: de cualquier manera está bien. Seguido por el énfasis de sus propias impresiones.

Introductorio, como también en los comentarios mencionados anteriormente, mi opinión es que C++se propone que las extensiones de encabezado sean.h si en realidad no hay ninguna razón en contra.

Dado que los documentos ISO / IEC usan esta notación de los archivos de encabezado y ni .hppsiquiera se produce una coincidencia de cadenas en sus documentaciones de idiomas sobreC++ .

Pero ahora estoy apuntando a una razón aceptable POR QUÉ de cualquier manera está bien, y especialmente por qué no está sujeto al lenguaje en sí.

Así que, aquí vamos.

La C++documentación (en realidad estoy tomando referencia de la versión N3690) define que un encabezado debe cumplir con la siguiente sintaxis:

2.9 Nombres de encabezado

header-name:
    < h-char-sequence >
    " q-char-sequence "
h-char-sequence:
    h-char
    h-char-sequence h-char
h-char:
    any member of the source character set except new-line and >
q-char-sequence:
    q-char
    q-char-sequence q-char
q-char:
    any member of the source character set except new-line and "

Entonces, como podemos extraer de esta parte, el nombre del archivo de encabezado también puede ser cualquier cosa que sea válida en el código fuente. Excepto que contenga '\n'caracteres y dependiendo de si se va a incluir, <>no está permitido que contenga a >. O a la inversa, si está incluido por ""-include, no está permitido contener un" .

En otras palabras: si tenía un entorno que admitiera nombres de archivo como prettyStupidIdea.>, incluya como:

#include "prettyStupidIdea.>"

sería válido, pero:

#include <prettyStupidIdea.>>

Sería inválido. Al revés lo mismo.

E incluso

#include <<.<>

sería un nombre de archivo de encabezado válido incluido

Incluso esto se conformaría C++, sería una idea bastante bastante estúpida, aunque.

Y por eso también .hppes válido.

¡Pero no es el resultado de que los comités diseñen decisiones para el idioma!

Entonces, discutir sobre el uso .hppes lo mismo que hacerlo .cc, .mmo sobre cualquier otra cosa que lea en otras publicaciones sobre este tema.

Tengo que admitir que no tengo ni idea de dónde .hppvino 1 , pero apostaría a que un inventor de alguna herramienta de análisis, IDE u otra cosa relacionada C++tuvo esta idea para optimizar algunos procesos internos o simplemente inventar algunos (probablemente incluso para ellos necesariamente ) nuevas convenciones de nomenclatura.

Pero no es parte del lenguaje.

Y cada vez que uno decide usarlo de esta manera. Que sea porque le gusta la mayor parte o porque algunas aplicaciones de flujo de trabajo lo requieren, nunca 2 es un requisito de la lengua. Entonces, quien dice "el pp es porque se usa con C ++", simplemente está equivocado con respecto a la definición de los lenguajes.

C ++ permite cualquier cosa que respete el párrafo anterior. Y si hay algo que el comité propuso usar, entonces lo está usando .hya que esta es la extensión demandada en todos los ejemplos del documento ISO.

Conclusión:

Mientras no vea / sienta la necesidad de usar .hmás .hppo viceversa, no debe molestarse. Porque ambos serían un nombre de encabezado válido de la misma calidad con respecto al estándar. Y, por lo tanto, cualquier cosa que REQUIERA que use .ho .hppes una restricción adicional del estándar que incluso podría estar en contradicción con otras restricciones adicionales que no se ajustan entre sí. Pero como OP no menciona ninguna restricción de idioma adicional, esta es la única respuesta correcta y aprobable a la pregunta

" * .h o * .hpp para sus definiciones de clase " es:

Ambos son igualmente correctos y aplicables siempre que no existan restricciones externas.


1 Por lo que sé, aparentemente, es el marco de impulso que surgió con esa .hppextensión.

2 ¡ Por supuesto que no puedo decir qué traerán algunas versiones futuras!


7

Prefiero .hpp para C ++ para dejar en claro tanto a los editores como a otros programadores que es un encabezado de C ++ en lugar de un archivo de encabezado de C.


6

C ++ ("C Plus Plus") tiene sentido como .cpp

Tener archivos de encabezado con una extensión .hpp no ​​tiene el mismo flujo lógico.


6

Puedes llamar a tus incluye lo que quieras.

Solo necesita especificar ese nombre completo en el #include.

Sugiero que si trabajas con C para usar .hy cuando con C ++ para usar .hpp.

Al final es solo una convención.


5

Codegear C ++ Builder utiliza .hpp para los archivos de encabezado generados automáticamente a partir de los archivos fuente de Delphi, y los archivos .h para sus "propios" archivos de encabezado.

Entonces, cuando escribo un archivo de encabezado C ++ siempre uso .h.


5

En uno de mis trabajos a principios de los 90, utilizamos .cc y .hh para los archivos fuente y de cabecera respectivamente. Todavía lo prefiero a todas las alternativas, probablemente porque es más fácil de escribir.


5

Bjarne Stroustrup y Herb Sutter tienen una declaración sobre esta pregunta en sus directrices básicas de C ++ que se encuentran en: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#S-source que también se refiere a los últimos cambios en la extensión estándar (C ++ 11, C ++ 14, etc.)

SF.1: Use un sufijo .cpp para archivos de código y .h para archivos de interfaz si su proyecto Y ya no sigue otra convención Motivo

Es una convención de larga data. Pero la coherencia es más importante, por lo que si su proyecto usa algo más, siga eso. Nota

Esta convención refleja un patrón de uso común: los encabezados se comparten con mayor frecuencia con C para compilar como C ++ y C, que generalmente usa .h, y es más fácil nombrar todos los encabezados .h en lugar de tener diferentes extensiones solo para los encabezados destinados para compartir con C. Por otro lado, los archivos de implementación rara vez se comparten con C y, por lo tanto, normalmente se deben distinguir de los archivos .c, por lo que normalmente es mejor nombrar todos los archivos de implementación de C ++ de otra manera (como .cpp).

Los nombres específicos .h y .cpp no ​​son obligatorios (solo se recomiendan por defecto) y otros nombres se usan ampliamente. Los ejemplos son .hh, .C y .cxx. Use tales nombres de manera equivalente. En este documento, nos referimos a .h y .cpp> como una forma abreviada de encabezado y archivos de implementación, aunque la extensión real puede ser diferente.

Su IDE (si usa uno) puede tener opiniones firmes sobre suficientes.

No soy un gran admirador de esta convención porque si está utilizando una biblioteca popular como boost, su consistencia ya está rota y debería usar mejor .hpp.


4

Como muchos aquí ya han mencionado, también prefiero usar .hpp para bibliotecas de solo encabezado que usan clases / funciones de plantilla. Prefiero usar .h para archivos de encabezado acompañados de archivos fuente .cpp o bibliotecas compartidas o estáticas.

La mayoría de las bibliotecas que desarrollo están basadas en plantillas y, por lo tanto, solo necesitan encabezados, pero cuando escribo aplicaciones tiendo a separar la declaración de la implementación y terminar con archivos .h y .cpp


3

Afortunadamente, es simple.

Debe usar la extensión .hpp si está trabajando con C ++ y debe usar .h para C o mezclar C y C ++.


2

Uso .h porque eso es lo que usa Microsoft, y lo que crea su generador de código. No hay necesidad de ir contra la corriente.


no en todas partes, en muchos ejemplos (eq WINDDK) usan .hpp
marsh-wiggle

13
No llamaría a Microsoft 'el grano' cuando se trata de C ++.
developerbmw

@Brett es cuando ese es tu trabajo. E incluso si no lo es, es un compilador muy popular.
Mark Ransom

@MarkRansom Me refería más a la historia de Microsoft de usar C. IMO VC ++ es un excelente compilador.
developerbmw

1
@developerbmw Yo diría que MSVC es el grano para los programas de Windows, y GCC es el grano para los programas * nix, personalmente. Son los que la mayoría de los otros compiladores para esas plataformas tienden a tratar de seguir siendo compatibles, que yo sepa.
Justin Time - Restablece a Monica el

1

En "El lenguaje de programación C ++, tercera edición de Bjarne Stroustrup", el libro de C ++ que no se debe leer, utiliza * .h. Así que supongo que la mejor práctica es usar * .h.

Sin embargo, * .hpp también está bien.


1
Si alguien escribió un libro sobre algo que aprendió de otros que lo aprendieron de otro libro (tal vez con suerte el mismo), escrito por alguien que tal vez tenía la fuente principal disponible, entonces es lo que están haciendo, pero no la marca para siendo la mejor práctica.
Dhein

Solo para mencionar: en realidad voté por esto. Pero lo habría votado si dijera "ISO / IEC N3690" o cualquier otro borrador de C ++ en lugar de "The C ++ Programming Language, Third Edition by Bjarne Stroustrup". Si bien este habría sido un punto válido, ya que .hppel lenguaje en sí no lo menciona en absoluto.
Dhein

99
@zaibis sabes que Bjarne Stroustrup inventó C ++ ¿verdad?
tumtumtum

@tumtumtum: admití que no estaba al tanto de esto. Pero de todos modos, incluso en ese caso, sigue siendo el documento del comité, manteniendo el estándar, que es la referencia a tomar. Incluso si él es el inventor del lenguaje, ya no es su decisión. Entonces, si bien esto hace que esta respuesta sea más valiosa, todavía no es un razonamiento válido.
dhein

1

Es fácil para las herramientas y los humanos diferenciar algo . Eso es.

En el uso convencional (por impulso, etc.), se .hpptrata específicamente de encabezados C ++. Por otra parte,.h es solo para encabezados que no son C ++ (principalmente C). Detectar con precisión el idioma del contenido es generalmente difícil, ya que hay muchos casos no triviales, por lo que esta diferencia a menudo hace que una herramienta lista para usar sea fácil de escribir. Para los humanos, una vez que se obtiene la convención, también es fácil de recordar y fácil de usar.

Sin embargo, señalaría que la convención en sí no siempre funciona, como se esperaba.

  • No está forzado por la especificación de lenguajes , ni C ni C ++. Existen muchos proyectos que no siguen la convención. Una vez que necesite fusionarlos (mezclarlos), puede ser problemático.
  • .hppen sí no es la única opción. ¿Por qué no .hho .hxx? (Aunque de todos modos, generalmente necesita al menos una regla convencional sobre nombres de archivo y rutas).

Yo personalmente uso ambos .hy .hppen mis proyectos de C ++. No sigo la convención anterior porque:

  • Los idiomas utilizados por cada parte de los proyectos están explícitamente documentados. No hay posibilidad de mezclar C y C ++ en el mismo módulo (directorio). Se requiere que cada biblioteca de terceros cumpla con esta regla.
  • Las especificaciones de idioma conformadas y los dialectos de idioma permitidos utilizados por los proyectos también están documentados. (De hecho, incluso documenté la fuente de las características estándar y la corrección de errores (en el estándar de idioma) que se usa ). Esto es algo más importante que distinguir los idiomas usados, ya que es demasiado propenso a errores y el costo de la prueba (p. Ej. la compatibilidad del compilador) puede ser significativa (complicada y lenta), especialmente en un proyecto que ya está en C ++ casi puro . Los nombres de archivo son demasiado débiles para manejar esto.
  • Incluso para el mismo dialecto de C ++, puede haber propiedades más importantes adecuadas a la diferencia. Por ejemplo, vea la convención a continuación.
  • Los nombres de archivo son esencialmente piezas de metadatos frágiles. La violación de la convención no es tan fácil de detectar. Para ser estable al tratar el contenido, una herramienta eventualmente no solo dependerá de los nombres. La diferencia entre extensiones es solo una pista. Tampoco debería esperarse que las herramientas que lo utilizan se comporten de la misma manera todo el tiempo, por ejemplo, detección de idioma de .harchivos en github.com (Puede haber algo en comentarios como shebang para que estos archivos de origen sean mejores metadatos, pero incluso no es convencional como los nombres de archivo, por lo que tampoco es confiable en general).

Usualmente uso .hppen encabezados de C ++ y los encabezados deben usarse (mantenerse) de una manera de solo encabezado , por ejemplo, como bibliotecas de plantillas. Para otros encabezados .h, hay un .cpparchivo correspondiente como implementación o es un encabezado que no es C ++. Este último es trivial para diferenciar a través del contenido del encabezado por humanos (o por herramientas con metadatos incrustados explícitos, si es necesario).


0

La extensión del archivo fuente puede tener significado para su sistema de compilación, por ejemplo, puede tener una regla en su archivo MAKE para .cppo .carchivos, o su compilador (por ejemplo, Microsoft cl.exe) puede compilar el archivo como C o C ++ dependiendo de la extensión.

Como debe proporcionar el nombre de archivo completo a la #includedirectiva, la extensión del archivo de encabezado es irrelevante. Puede incluir un .carchivo en otro archivo fuente si lo desea, porque es solo una inclusión textual. Su compilador podría tener una opción para volcar el resultado preprocesado que lo aclarará (Microsoft: /Ppreprocesar para archivar, /Epreprocesar stdout, /EPomitir #linedirectivas, /Cretener comentarios)

Puede optar por usar .hpppara archivos que solo son relevantes para el entorno de C ++, es decir, usan funciones que no se compilan en C.


0

No hay ninguna ventaja en ninguna extensión en particular, aparte de que puede tener un significado diferente para usted, el compilador y / o sus herramientas. header.hes un encabezado válido header.hppes un encabezado válido header.hhes un encabezado válido header.hxes un encabezado válido h.headeres un encabezado válido this.is.not.a.valid.headeres un encabezado válido en negación. ihjkflajfajfklafes un encabezado válido Mientras el compilador pueda analizar el nombre correctamente y el sistema de archivos lo admita, es un encabezado válido, y la única ventaja de su extensión es lo que se lee en él.

Dicho esto, es muy útil poder hacer suposiciones con precisión basadas en la extensión , por lo que sería aconsejable utilizar un conjunto de reglas fácilmente comprensibles para sus archivos de encabezado. Personalmente, prefiero hacer algo como esto:

  1. Si ya hay pautas establecidas, sígalas para evitar confusiones.
  2. Si todos los archivos de origen en el proyecto son para el mismo idioma, use .h. No hay ambigüedad.
  3. Si algunos encabezados son compatibles con varios idiomas, mientras que otros solo son compatibles con un solo idioma, las extensiones se basan en el idioma más restrictivo con el que un encabezado es compatible. Un encabezado compatible con C, o con ambos C y C ++, recibe .h, mientras que una cabecera compatible con C ++, pero no consigue C .hppo .hho algo por el estilo.

Esto, por supuesto, es solo una de las muchas maneras de manejar extensiones, y no necesariamente puede confiar en su primera impresión, incluso si las cosas parecen sencillas. Por ejemplo, he visto mencionar el uso .hde encabezados normales y .tppencabezados que solo contienen definiciones para funciones miembro de clase con plantilla, con .harchivos que definen clases con plantilla, incluidos los .tpparchivos que definen sus funciones miembro (en lugar del .hencabezado que contiene directamente ambos declaración de función y la definición). Para otro ejemplo, muchas personas siempre reflejan el idioma del encabezado en su extensión, incluso cuando no hay posibilidad de ambigüedad; para ellos, .hsiempre es un encabezado C y .hpp(o.hh , o.hxx, etc.) es siempre un encabezado de C ++. Y una vez más, algunas personas usan .h"encabezado asociado con un archivo fuente" y .hpp"encabezado con todas las funciones definidas en línea".

Considerando esto, la principal ventaja vendría consistentemente nombrar sus encabezados en el mismo estilo, y hacer que ese estilo sea fácilmente evidente para cualquiera que examine su código. De esta manera, cualquier persona familiarizada con su estilo de codificación habitual podrá determinar lo que quiere decir con cualquier extensión dada con solo una mirada superficial.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.