archivos de plantilla y encabezado c ++ [duplicate]

4 minutos de lectura

archivos de plantilla y encabezado c duplicate
kamikaze_piloto

Entonces, escuché que las plantillas de C++ no deben separarse en archivos de encabezado (.h) y fuente (.cpp).

Por ejemplo, una plantilla como esta:

template <class T>
class J
{   
   T something;
};

¿Es esto cierto? ¿Por que es esto entonces?

Si por eso voy a tener que poner tanto la declaración como la implementación en el mismo archivo, ¿debería ponerlo en un archivo .h o en un archivo .cpp?

archivos de plantilla y encabezado c duplicate
Carreras de ligereza en órbita

Encabezados.

Esto se debe a que las plantillas se instancian en tiempo de compilación, no en tiempo de enlace, y diferentes unidades de traducción (más o menos equivalentes a su .cpp archivos) solo “se conocen” entre sí en el momento del enlace. Los encabezados tienden a ser ampliamente “conocidos” en tiempo de compilación porque #include en cualquier unidad de traducción que los necesite.

Leer https://isocpp.org/wiki/faq/templates para más.

  • esta es la respuesta más clara en esta pregunta y la original

    – csguy

    09 dic. 19 en 05:28

1642937465 673 archivos de plantilla y encabezado c duplicate
Chris A.

La razón por la que no puede poner una clase con plantilla en un archivo .cpp es porque para “compilar” un archivo .cpp necesita saber qué tipo se está utilizando en lugar de T. Tal como está una clase con plantilla ( como su clase J) no tiene suficiente información para compilar. Por lo tanto, debe estar todo en los encabezados.

Si desea dividir la implementación en otro archivo para mayor limpieza, la mejor práctica es usar un archivo .hxx. Así: dentro de su archivo de encabezado, Jh, ponga:

#ifndef _J_H__
#define _J_H__

template <class T> class J{  // member definitions };

#include "j.hxx"

#endif // _J_H__

y luego, en j.hxx tendrás

template <class T> J<T>::J() { // constructor implementation }

template <class T> J<T>::~J() { // destructor implementation }

template <class T> void J<T>::memberFunc() { // memberFunc implementation }

// etc.

Finalmente, en su archivo .cpp que usa la clase con plantilla, llamémoslo K.cpp, tendrá:

#include "J.h" // note that this always automatically includes J.hxx    
void f(void)
{
     J<double> jinstance;  // now the compiler knows what the exact type is.
}

  • No estoy seguro sobre el uso de la .hpp extensión. Por convención, en C++ .h y .hpp son bastante intercambiables, por lo que no está imbuyendo j.hpp con un nombre de archivo que lo distingue funcionalmente de J.h. La convención aquí sería J.hxx.

    – Carreras de ligereza en órbita

    26 oct.


  • +1 Buen punto, y siempre he usado .hxx en la práctica también (principalmente aprendiendo de los ejemplos de otros), pero nunca entendí por qué era correcto hasta ahora.

    – Chris A.

    26 oct.


  • Si puedo preguntar, ¿de qué sirve esto? Al final, cada archivo #incluido .cpp se vuelve a compilar si el .h o Se modifican los archivos .hxx; y modificando la implementación donde está en .h (no este ejemplo; quiero decir, cuando toda la plantilla está en .h) debería ser prácticamente idéntica, mecánicamente, ¿no?

    – Noein

    30 mar. 15 a las 19:39

  • Es idéntico al compilador y es simplemente una convención que he visto en la práctica y que me ha gustado. Según mi experiencia, solo se trata de dividir la implementación para que pueda tener un archivo .h corto con implementaciones de clases con plantilla en el archivo .hxx. Si tienes pruebas de lo contrario, házmelo saber.

    – Chris A.

    31 mar. 15 a las 23:08

  • ¿Para qué se queda .hxx?

    – Nick

    25 mar. 16 a las 21:53

Sí, es verdad. La declaración y la implementación generalmente se colocan juntas en el archivo de encabezado. Algunos compiladores experimentaron con un export palabra clave que permitiría separarlos, pero que se eliminó de C++ 0x. Verificar esta entrada de preguntas frecuentes por todos los detalles sucios.

Si necesita que otras unidades de traducción (archivos .cpp) puedan usar el código de la plantilla, debe colocar la implementación en el archivo .h o, de lo contrario, esas otras unidades no podrán crear una instancia de la plantilla (expándala de acuerdo con el tipos que utilizan).

Si su función de plantilla solo se instancia en un archivo .cpp, puede definirla allí. Esto sucede a veces cuando una clase tiene una función miembro privada que es una plantilla (y solo se llama desde el archivo de implementación, no desde el archivo de encabezado de la clase).

.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad