2011-04-10 48 views
24

por lo que se enteraron de que las plantillas de C++ no deben ser separados en un .hy .cpp ...C++ plantilla y archivos de cabecera

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 declaración e implementación en el mismo archivo, ¿debería ponerlo en un archivo .h o en un archivo .cpp?

+0

existe una respuesta en el C++ FAQ: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12 – birryree

Respuesta

23

Encabezados.

Es porque las plantillas se instancian en tiempo de compilación, no en tiempo de enlace, y las diferentes unidades de traducción (aproximadamente equivalentes a sus archivos .cpp) solo se "conocen" entre sí en el tiempo de enlace. Los encabezados tienden a ser ampliamente "conocidos" en tiempo de compilación porque usted los #include en cualquier unidad de traducción que los necesite.

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

2

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 esas otras unidades no podrán instanciar la plantilla (expandir de acuerdo con los tipos que usan).

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 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).

4

Sí, es cierto. La declaración y la implementación generalmente se incluyen en el archivo de encabezado. Algunos compiladores experimentaron con una palabra clave export que les permitiría separarse, pero que se ha eliminado de C++ 0x. Consulte this FAQ entry para conocer todos los detalles sucios.

12

La razón por la que no puede poner una clase con plantilla en un archivo .cpp es porque para "compilar" un archivo .cpp debe saber cuál es el tipo que 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 ser todo en encabezados.

Si desea dividir la implementación en otro archivo para la limpieza, la mejor práctica es utilizar un archivo .hxx. De esta manera: dentro de su archivo de cabecera, JH, poner:

#ifndef _J_H__ 
#define _J_H__ 

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

#include "j.hxx" 

#endif // _J_H__ 

y luego, en j.hxx usted tendrá

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. 

último en su archivo .cpp que utiliza la clase de plantilla, vamos llamarlo 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. 
} 
+2

I' m no estoy seguro sobre el uso de la extensión '.hpp'. 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'.] (Http://bytes.com/topic/c/answers/132004-inline-template-file-extensions) –

+0

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

+0

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

Cuestiones relacionadas