Comprender este problema consiste básicamente en comprender cómo funcionan las unidades de compilación de C++. Las cosas en los archivos de encabezado se pegan básicamente en el código fuente de un conjunto completo de unidades de compilación mediante declaraciones #include
. Cada unidad de compilación se compila en un archivo de objetos, los archivos de objeto se vinculan y se generan conflictos debido a que esas cosas se replican por todas partes.
Las excepciones son cosas que (históricamente, al menos) no entran en el archivo objeto porque el compilador las trata directamente (por ejemplo, funciones en línea) y cosas que no se pueden compilar en una unidad y luego enlazar a otro porque no están completamente definidos (plantillas). Las funciones de plantilla a menudo obtienen idénticas instancias en varias unidades de compilación, y el enlazador tiene una inteligencia especial para descartar los duplicados.
Esto significa que la separación de la interfaz y la implementación en los archivos de encabezado y cuerpo no es muy clara. Ada tiene una separación mucho más limpia, pero un proceso de construcción más complejo para compensar el IIRC. Java simplemente dejó caer los archivos separados para la interfaz y la implementación.
Los enlazadores se volvieron mucho más sofisticados a lo largo de los años y asumieron parte del trabajo del compilador, y muchas de estas explicaciones simplemente están equivocadas en estos días, pero los patrones básicos permanecen. Las funciones de plantilla y las funciones en línea pueden (y a menudo deben) ir en el encabezado, junto con todas las declaraciones compartidas de don't-direct-generate-object-code. Las definiciones de funciones normales no deberían estar en un archivo de encabezado.
En cuanto a las plantillas, no es estrictamente cierto que debe poner las definiciones de función (miembro) en el archivo de encabezado. Puede poner las definiciones en un archivo fuente y usar la creación de instancias explícitas para hacer que las especializaciones particulares estén disponibles ... –
@STingRaySC Sí, tuve algunos recuerdos vagos de C++ Templates de que es posible, aunque nunca lo he hecho yo mismo. Sin embargo, traté de dar una regla general que es buena para los principiantes y casi siempre aplicable. Entrar en los casos especiales es para los expertos (de los que no soy uno :-) –
Y no tiene que proporcionar implementaciones de plantilla en el archivo de encabezado si su compilador admite 'export' – smerlin