Plantilla c ++ y archivos de encabezado

Entonces, escuché que las plantillas de C ++ no deberían separarse en un encabezado (.h) y en archivos de origen (.cpp).

Por ejemplo, una plantilla como esta:

template  class J { T something; }; 

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

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

Encabezados

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

Lee https://isocpp.org/wiki/faq/templates para obtener más información.

La razón por la que no se puede poner una clase con plantilla en un archivo .cpp se debe a que para “comstackr” un archivo .cpp se necesita saber cuál es el tipo que se está utilizando en lugar de T. Como es una clase con plantilla ( como su clase J) no tiene suficiente información para comstackr. Por lo tanto, debe ser todo en encabezados.

Si desea dividir la implementación en otro archivo para la limpieza, la mejor práctica es usar un archivo .hxx. De esta manera: dentro de tu archivo de encabezado, Jh, pon:

 #ifndef _J_H__ #define _J_H__ template  class J{ // member definitions }; #include "j.hxx" #endif // _J_H__ 

y luego, en j.hxx tendrás

 template  J::J() { // constructor implementation } template  J::~J() { // destructor implementation } template  void J::memberFunc() { // memberFunc implementation } // etc. 

Finalmente, en su archivo .cpp que usa la clase de plantilla, vamos a llamarlo K.cpp, tendrá:

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

Sí, es verdad. La statement y la implementación generalmente se incluyen en el archivo de encabezado. Algunos comstackdores experimentaron con una palabra clave de export que les permitiría separarse, pero que se ha eliminado de C ++ 0x. Consulte esta entrada de Preguntas frecuentes para conocer todos los detalles sucios.

Si necesita que el código de la plantilla pueda ser utilizado por otras unidades de traducción (archivos .cpp), 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 (amplíelo según el tipos que usan).

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