español - Las plantillas de C++ declaran en.h, definen en.hpp
header template deviantart (7)
Vi un código en el que el desarrollador definió una plantilla de clase en un archivo .h, y definió sus métodos en un archivo .hpp. Esto me sorprendió un poco.
¿Existen convenciones particulares en C ++ cuando se trata de plantillas y en qué archivos deberían estar?
Por ejemplo, digamos que tenía una plantilla de clase Vector
con métodos para operaciones vectoriales (sumar, restar, punto, etc.). También me gustaría especializar ciertas funciones si el argumento de la plantilla es un float
(operadores de comparación). ¿Cómo separaría todo esto entre archivos (especifique si .h, .hpp, .cpp)?
Creo que un aspecto de la separación de la interfaz (.h) y el archivo de implementación (.hpp) es que un usuario de la plantilla (es decir, otro desarrollador) solo debería tener que mirar el archivo .h para entender cómo usar la plantilla sin estar Distraído por su implementación real.
Eso me suena inusual. La definición de una plantilla y todas las especializaciones deben compilarse junto con su declaración, con la excepción de export
plantillas de export
, una característica que efectivamente no existe.
C ++ 0x introduce declaraciones de plantillas extern
, que le permiten definir especializaciones explícitas en un archivo fuente diferente (unidad de traducción). Esto ya existe como una extensión en GCC y probablemente en otras plataformas.
Dividirse en dos archivos podría ayudar a "ocultar" un poco la implementación, o permitir algún tipo de pereza con el doxygen, tal vez.
Jajaja También es posible mejorar el tiempo de compilación con encabezados precompilados. El compilador puede almacenar en caché los encabezados por archivo. Una cabecera de "implementación" separada podría modificarse sin tocar la cabecera de "interfaz". Pero no al revés, el encabezado de implementación aún tomaría la mayor parte del tiempo de compilación, y la ganancia sería muy frágil y dependiente de la plataforma y los cambios específicos realizados. Al final, PCH mejora el tiempo en varios archivos de origen, y la optimización de las dependencias del encabezado no tiene sentido.
La biblioteca Boost utiliza ".hpp" para los encabezados que contienen la declaración Y la implementación. En tales casos, no es necesario enlazar con la biblioteca (precompilada).
Con respecto a la idea de Boost, una extensión como ".inl" podría ser una buena idea para describir el archivo fuente de "implementación" de un encabezado de declaración de plantilla.
Me parece que esta es una forma confusa de separar el código. .h
significa encabezado y .hpp
para .hpp
de C ++ comúnmente. Poner definiciones de plantillas en .hpp
mientras que otro código en .h
parece abusar de la extensión de archivo.
El código de la plantilla generalmente se escribe en un encabezado junto con la declaración de la plantilla, o en otro encabezado que también puede tener un sufijo especial como .tcc
o algo así y luego se incluye en el encabezado donde se colocan las declaraciones de la plantilla. Pero en realidad, la extensión del archivo No importa mientras seas consistente en tu proyecto.
Las excepciones son cuando usa la creación de instancias explícita y sabe exactamente qué instancias necesitará. Imagina que tienes una plantilla y exactamente dos instancias de ella:
template<typename T>
struct SymbolTable {
T *lookup();
// ...
};
template struct SymbolTable<GlobalSym>;
template struct SymbolTable<LocalSym>;
No es necesario poner la definición de lookup
y otras en el encabezado. Puede colocarlos todos en un archivo .cpp
, junto con las dos directivas de .cpp
instancias explícitas.
El último punto sobre el que pregunta es sobre un tema diferente: especializaciones explícitas. Te recomiendo que hagas una pregunta aparte sobre eso. En pocas palabras, las definiciones de especialización explícitas donde todos los argumentos de la plantilla tienen valores / tipos concretos deben incluirse en el archivo .cpp
, pero se necesitan declaraciones de los mismos en el encabezado (para indicar a otros que esos miembros están especializados).
Normalmente (en mi experiencia, YMMV) un archivo hpp
es un archivo CPP con #include
. Esto se hace para dividir el código en dos archivos físicos, uno de inclusión principal y un archivo de detalles de implementación que los usuarios de su biblioteca no necesitan conocer. Se hace así:
super_lib.h (el único archivo que sus clientes necesitan para #include
)
template<...> class MyGizmo
{
public:
void my_fancy_function();
};
#include "super_lib_implementation.hpp"
super_lib_implementation.hpp (sus clientes no #include
esto directamente)
template<...> void MyGizmo<...>::my_fancy_function()
{
// magic happens
}
Nunca he oído hablar de poner declaraciones de clase en .h
y definiciones de plantillas en .hpp
. Todos los proyectos que he visto han adoptado el enfoque de que .h
y .hpp
significan lo mismo y usted debe estandarizar uno (generalmente .h
).
Los métodos de plantilla se pueden colocar al final del archivo .h
, o se pueden colocar en archivos -inl.h
separados (como lo sugiere la Guía de estilo de Google C ++ , por ejemplo).
Si definimos una plantilla de clase en un archivo .h, y definimos sus métodos en un archivo .hpp, entonces tenemos que #include
incluir el archivo .hpp en el archivo .h. Es más fácil simplemente definir métodos al final del archivo .h (entonces no se necesita un archivo .hpp).