Problema.
Se trata de un problema habitual en C++, que normalmente pasa desapercibido en códigos mucho más complejos pero en tu caso es muy fácil de localizar:
Te falta la definición de la función S::dos
Solución.
Añade esta línea en S.cpp
:
int S::dos() { lo que toque... }
Explicación.
El enlazador no ha sido incapaz de encontrar la Unidad de Traducción en que la función S::dos
estaba definida, y al intentar generar el programa final ha fallado porque le faltaba una de las piezas necesarias.
Para entender esto, debemos conocer el concepto de Unidad de Traducción.
Unidad de Traducción (UdT).
Una UdT es, a grandes rasgos el resultado intermedio de procesar y compilar un archivo de código. Es decir: el preprocesador ha realizado sus tareas (incluir cabeceras #include
, expandir macros #define
, descartar código en compilación condicional #ifdef
, #else
, #endif
) y el compilador ha realizado una compilación con el archivo resultante, dicha compilación va a parar a un archivo objeto y el enlazado entre archivos objetos es lo que acaba generando el programa final.
Dado que una UdT contiene el resultado de compilar código, sólo generarán archivos objeto aquellos archivos de código que contengan código compilable; En otras palabras un archivo de código que tan sólo contenga declaraciones (por ejemplo una cabecera .h
o .hpp
1) no generará archivo objeto ni consistirá en una UdT pero un archivo de código con definiciones (por ejemplo un archivo .c
o .cpp
1) será una UdT y generará un archivo objeto.
Cada UdT dispondrá de las entidades (objetos, funciones, enumerados) que hayan sido compiladas en su archivo de objeto:
En este ejemplo el objeto S
tiene dos funciones (S::uno
y S::dos
) que son compiladas y van a parar al archivo objeto S.obj
que es la representación binaria de la UdT de S.cpp
. Si en algún otro punto del programa se requiere el uso de un objeto de tipo S
(porque alguien ha incluido S.hpp
y ha usado alguna de sus funciones) el enlazador buscará el archivo objeto que contenga estas funciones y lo usará para crear el programa final. Las definiciones de un objeto no tienen por qué estar en un sólo archivo de código, pueden estar dispersas en otros archivos y cada uno de ellos creará su UdT:
Será el enlazador el que se encargue después de juntar todas las piezas para crear el programa, pero si entre todos los archivos objeto disponibles para el enlazador, no se encuentra alguna de las definiciones requeridas se provocará un fallo de enlazado como el que has experimentado:
1La extensión del archivo es irrelevante, lo importante es el contenido del archivo.