Tiene que haber una buena respuesta para esto pero también voy a lanzar la mía a la piscina.
C++ permite que las declaraciones y las implementaciones de las estructuras del programa se realicen por separado. Se deriva de cómo los programadores C/C++ publican nuevas funcionalidades entre sí: los archivos de encabezado se incluyen en unidades de compilación dependientes en lugar de las unidades que dependen de los metadatos presentes en la compilación (como es de esperar si trabajas con C# o Java).
Cada vez que dar el compilador una instrucción si se trata de una declaración ("habrá esta cosa con esta interfaz") o una aplicación ("aquí es esta cosa con esta interfaz y estos comportamientos"), usted tener la oportunidad de adaptar esa directiva.
El hecho de que tenga una opción para hacerlo, en lugar de un requisito para hacerlo, le brinda mucha más flexibilidad de la que le ofrecen los lenguajes más modernos como Java y C#.
Considérese la siguiente plantilla (estoy oxidado así que sea amable con problemas sintácticos mínimos, por favor):
template<typename Junk>
class IGotJunk {
private:
Junk myJunk_;
public:
void SetJunk(Junk const& source);
Junk const& GetJunk() const;
}
su aplicación "típico" de dicha plantilla podría incluir estos comportamientos predeterminados:
template<typename Junk>
void IGotJunk<Junk>::SetJunk(Junk const& source)
{
myJunk_ = source;
}
Sin embargo, para las cadenas, existe el riesgo de que la cadena se modifique después de que se copie el puntero, en cuyo caso, podría proporcionar un comportamiento especializado que asegure que la cadena se copie, en lugar del puntero (nuevamente, ha sido un largo, largo tiempo) ...
void IGotJunk<char*>::SetJunk(char* const& source)
{
free(myJunk_);
myJunk_ = malloc(strlen(source) + 1);
strcpy(myJunk_, source);
}
Luego podría hacer algo similar para GetJunk(). Esa es probablemente la razón por la que debe declarar los parámetros de plantilla para cada artefacto que cree: porque es posible que no desee que sean los mismos en todos los casos.
Otros han dado buenas respuestas. Simplemente señalaré que en algún lugar de los encabezados estándar de la biblioteca encontrará cosas similares para, por ejemplo, std :: map :: insert - std :: map, std :: set y std :: vector y otros contenedores estándar son todas clases de plantillas. – Steve314