¿Por qué la implementación y la declaración de una clase de plantilla deben estar en el mismo archivo de encabezado? ¿Podría alguno de ustedes explicarlo por ejemplo?¿Por qué la implementación y la declaración de una clase de plantilla deben estar en el mismo archivo de encabezado?
Respuesta
El compilador necesita tener acceso a toda la definición de plantilla (no solo a la firma) para generar código para cada instanciación de la plantilla, por lo que debe mover las definiciones de las funciones a su encabezado. Para obtener más información, visite The Inclusion Model.
No, no es así. Podría escribir la definición manualmente en cada TU, pero, por supuesto, la convención de encabezado está diseñada para ayudarlo a evitar tales tonterías :) –
@LightnessRacesinOrbit ¿puedo preguntar qué es TU? – athos
@athos http://en.wikipedia.org/wiki/Translation_unit_%28programming%29 –
La definición de una plantilla de clase y la implementación de sus funciones miembro debe estar visible para cada lugar que la ejemplifique con un tipo distinto. es decir, para crear una instancia de myTemplate<int>
, necesita ver la definición e implementación completa de myTemplate
.
La forma más sencilla de hacerlo es colocar la definición de la plantilla y sus funciones miembro en el mismo encabezado, pero hay otras formas. Por ejemplo, podría poner las implementaciones de funciones miembro en un archivo separado que se incluyó por separado. Luego podría incluirlo desde el primer encabezado o solo incluir el archivo de implementación donde lo necesitó.
Por ejemplo, una práctica es crear una instancia explícita de una plantilla para un conjunto distinto de parámetros en un archivo .cpp y declarar esas instancias extern
en el encabezado. De esta forma, esas instancias se pueden usar en otros archivos fuente sin que sea necesario que la implementación de las funciones del miembro de la plantilla sea visible. Sin embargo, a menos que incluya el archivo de implementación, no podrá usar otros conjuntos de parámetros de plantilla.
es decir, si tiene myTemplate<int>
y myTemplate<std::string>
define como extern
entonces usted puede usarlos bien, pero si no se define myTemplate<double>
extern
entonces no se puede utilizar que sin la aplicación.
En el caso de una clase normal, la declaración es suficiente para la compilación, y las definiciones correspondientes serán vinculadas.
En el caso de las plantillas, el compilador también necesita la definición para generar el código.
La diferencia se explica mejor en el C++ FAQ.
No es necesario.
Lo que es necesario es que la definición de la plantilla sea visible en el momento de la instanciación (donde se usa) para que el compilador pueda derivar la clase/función de la plantilla en este momento.
Sin embargo, es muy común el uso de dos archivos de cabecera para las clases de plantilla:
// foo_fwd.hpp
template <typename T, typename U> struct Foo;
// foo.hpp
#include "foo_fwd.hpp"
template <typename T, typename U> struct Foo { typedef std::pair<T,U> type; };
Esto permite que aquellos que no necesitan la definición de plantilla completa para incluir una cabecera algo más ligero, por ejemplo:
//is_foo.hpp
#include <boost/mpl/bool.hpp>
#include "foo_fwd.hpp"
template <typename Z>
struct is_foo: boost::mpl::false_ {};
template <typename T, typename U>
struct is_foo< Foo<T,U> >: boost::mpl::true_ {};
que puede acelerar un poco el tiempo de compilación.
- 1. ¿Por qué incluir un encabezado y reenviar declarar la clase contenida en el mismo archivo cpp?
- 2. C++: ¿las funciones de amigo deben estar definidas en el archivo de encabezado?
- 3. Definiciones de plantilla fuera de declaración para el método de plantilla en la clase de plantilla
- 4. ¿La definición de funciones en línea de C++ debe estar en el mismo archivo?
- 5. ¿Por qué no puedo poner una declaración de "uso" dentro de una declaración de clase?
- 6. Declaración de la variable en un archivo de encabezado
- 7. Declaración de especialización de miembro de clase de plantilla
- 8. Declaración de la función Obj-C en el encabezado
- 9. ¿Los campos de instancia/clase deben estar prefijados en Delphi?
- 10. Derivar una clase de plantilla de sí mismo en C++
- 11. ¿Por qué no puedo ver una plantilla de archivo de clase de objetos administrados en Xcode?
- 12. ¿Por qué la primera lista de parámetros de una clase no puede estar implícita?
- 13. Cómo definir la función de plantilla dentro de clase de plantilla en el archivo * .INL
- 14. ¿Por qué no puedo definir funciones C simples en el archivo de encabezado?
- 15. declaración Forward de la clase utilizada en función de plantilla no es compilada por sonido metálico ++
- 16. El constructor de plantillas en la clase de plantilla debe definirse en la definición de clase?
- 17. Incluyendo .cpp al final del archivo de encabezado de plantilla
- 18. ¿Cómo compilar y vincular archivos de objeto en C++ usando el mismo archivo de encabezado?
- 19. plantilla de clase llamado X en la clase de plantilla
- 20. ¿Por qué "se extiende" precede a "instrumentos" en la declaración de la clase
- 21. ¿Por qué poner una declaración y definición de clase en dos archivos separados en C++?
- 22. ¿Debe una función auxiliar ir en el encabezado o en el archivo de implementación?
- 23. En SIP, por qué el campo de encabezado de contacto DEBE estar presente en la solicitud de invitación
- 24. Sintaxis para el constructor en la clase de plantilla
- 25. ¿Por qué el compilador selecciona el constructor de la clase base dentro de la lista de argumentos de la plantilla?
- 26. Tipo/valor de desajuste en la plantilla C++ declaración de la clase
- 27. Por qué solo una clase por archivo
- 28. Defina la clase consigo mismo como implementación genérica. ¿Por qué/cómo funciona esto?
- 29. ¿Por qué la declaración de función de JavaScript (y expresión)?
- 30. Interfaz C# e implementación en el mismo archivo - ¿buena idea?
tienen que estar visibles dentro de la misma unidad de compilación.pueden estar en archivos diferentes si ambos están incluidos – Anycorn
De hecho, no es raro dividir la declaración y la implementación en dos archivos. El encabezado generalmente incluirá el archivo de implementación. – MSalters
@MSalters: lo cual es problemático con las clases de plantilla, de lo que se trata esta pregunta. Desearía poder rechazar los comentarios. –