Las soluciones a los ejercicios se pueden encontrar en el documento electrónico titulado «The Thinking in C++ Annotated Solution Guide», disponible por poco dinero en www.BruceEckel.com.
Cree una función con una variable estática que sea un puntero (con un argumento por defecto igual a cero). Cuando la función que realice la llamada proporcione un valor para ese argumento se usará para apuntar al principio de un array de int. Si se llama a la función con el argumento cero (utilizando el argumento por defecto), la función devuelve el siguiente valor del array, hasta que llegue a un valor -1 en el array (que actuará como señal de final). Experimente con esta función en main().
Cree una función que devuelva el siguiente valor de una serie de Fibonacci cada vez que sea llamada. Añada un argumento de tipo bool con valor por defecto false tal que cuando el argumento valga true «reinicie» la función al principio de la serie de Fibonacci. Experimente con esta función en main().
Cree una clase que contenga un array de int. Especifique la dimensión del array utilizando static const int dentro de la clase. Añada una variable const int e inicialícela en la lista de inicialización del constructor. Haga el constructor inline. Añada un atributo static int e inicialícelo a un valor específico. Añada un método estático que imprima el atributo estático. Añada un miembro inline llamado print() que imprima todos los valores del array y que llame al método estático. Experimente con esta clase en main().
Cree una clase llamada Monitor que mantenga el registro del número de veces que ha sido llamado su método incident(). Añada un método print() que muestre por pantalla el número de incidentes. Ahora cree una función global (no un método) que contenga un objeto estático Monitor. Cada vez que llame a la función debe llamar a incident(), después al método print() para sacar por pantalla el contador de incidentes. Experimente con la función en main().
Modifique la clase Monitor del Ejercicio 4 de forma que pueda decrementar (decrement()) el contador de incidentes. Cree una clase llamada Monitor2 que tome como argumento del constructor un puntero a Monitor1, y que almacene ese puntero y llame a incident() y print(). En el destructor para Monitor2, llame a decrement() y print(). Cree ahora un objeto estático de Monitor2 dentro de una función. Dentro de main(), experimente llamando y no llamando a la función para ver qué pasa con el destructor de Monitor2.
Cree un objeto global de clase Monitor2 y vea qué sucede.
Cree una clase con un destructor que imprima un mensaje y después llame a exit(). Cree un objeto global de esa clase y vea qué pasa.
En StaticDestructors.cpp, experimente con el orden de llamada de los constructores y destructores llamando a f() y g() dentro de main() en diferentes órdenes. ¿Su compilador inicializa los objetos de la forma correcta?
En StaticDestructors.cpp, pruebe el manejo de errores por defecto de su implementación convirtiendo la definición original de out en una declaración extern, y poniendo la definición real después de la definición de a (cuyo constructor de Obj manda información a out). Asegúrese de que no hay ningún otro programa importante funcionando en su máquina cuando ejecute el código o de que su máquina maneja los fallos de forma robusta.
Demuestre que las variables estáticas de fichero en los ficheros de cabecera no chocan entre sí cuando son incluidas en más de un fichero cpp.
Cree una clase sencilla que contenga un int, un constructor que inicialice el int con su argumento, un método que cambie el valor del int con su argumento y una función print() que muestre por pantalla el int. Coloque su clase en un fichero de cabecera e incluya dicho fichero en dos ficheros cpp. En uno de ellos cree una instancia de la clase y en el otro declare ese identificador como extern y pruébelo dentro de main(). Recuerde, debe enlazar los dos ficheros objeto o de lo contrario el enlazador no encontrará el objeto.
Cree la instancia del objeto del Ejercicio 11 como static y verifique que, debido a eso, el enlazador es incapaz de encontrarla.
Declare una función en un fichero de cabecera. Defina la función en un fichero cpp y llámela desde main() en un segundo fichero cpp. Compile y verifique que funciona. Ahora cambie la definición de la función de forma que sea static y verifique que el enlazador no puede encontrarla.
Modifique Volatile.cpp del Capítulo 8 para hacer que comm::isr() funcione realmente como una rutina de servicio de interrupción. Pista: una rutina de servicio de interrupción no toma ningún argumento.
Escriba y compile un programa sencillo que utilice las palabras reservadas auto y register.
Cree un fichero de cabecera que contenga un espacio de nombres. Dentro del espacio de nombres cree varias declaraciones de funciones. Cree ahora un segundo fichero de cabecera que incluya el primero y continúe el espacio de nombres, añadiendo varias declaraciones de funciones más. Cree ahora un fichero cpp que incluya el segundo fichero de cabecera. Cree un alias (más corto) para su espacio de nombres. Dentro de una definición de función, llame a una de sus funciones utilizando la resolución de ámbito. Dentro de una definición de función separada, escriba una directiva using para introducir su espacio de nombres en el ámbito de esa función, y demuestre que no necesita utilizar la resolución de ámbito para llamar a las funciones de su espacio de nombres.
Cree un fichero de cabecera con un espacio de nombres sin nombre. Incluya la cabecera en dos ficheros cpp diferentes y demuestre que un espacio sin nombre es único para cada unidad de traducción.
Utilizando el fichero de cabecera del Ejercicio 17, demuestre que los nombres de un espacio de nombres sin nombre están disponibles automáticamente en una unidad de traducción sin calificación.
Modifique FriendInjection.cpp para añadir una definición para la función amiga y para llamar a la función desde main().
En Arithmetic.cpp, demuestre que la directiva using no se extiende fuera de la función en la que fue creada.
Repare el problema de OverridingAmbiguity.cpp, primero con resolución de ámbito y luego, con una declaración using que fuerce al compilador a escoger uno de los nombres de función idénticos.
En dos ficheros de cabecera, cree dos espacios de nombres, cada uno conteniendo una clase (con todas las definiciones inline) con idéntico nombre que el del otro espacio de nombres. Cree un fichero cpp que incluya ambos ficheros. Cree una función y, dentro de la función, utilice la directiva using para introducir ambos espacios de nombres. Pruebe a crear un objeto de la clase y vea qué sucede. Haga las directivas using globales (fuera de la función) para ver si existe alguna diferencia. Repare el problema usando la resolución de ámbito, y cree objetos de ambas clases.
Repare el problema del Ejercicio 22 con una declaración using que fuerce al compilador a escoger uno de los nombres de clase idénticos.
Extraiga las declaraciones de espacios de nombres de BobsSuperDuperLibrary.cpp y UnnamedNamespaces.cpp y póngalas en ficheros de cabecera separados, dando un nombre al espacio de nombres sin nombre en el proceso. En un tercer fichero de cabecera, cree un nuevo espacio de nombres que combine los elementos de los otros dos espacios de nombres con declaraciones using. En main(), introduzca su nuevo espacio de nombres con una directiva using y acceda a todos los elementos de su espacio de nombres.
Cree un fichero de cabecera que incluya <string> y <iostream> pero que no use ninguna directiva using ni ninguna declaración using. Añada guardas de inclusión como ha visto en los ficheros de cabecera del libro. Cree una clase con todas las funciones inline que contenga un atributo string, con un constructor que inicialice ese string a partir de su argumento y una función print() que muestre por pantalla el string. Cree un fichero cpp y pruebe su clase en main().
Cree una clase que contenga un static double y long. Escriba un método estático que imprima los valores.
Cree una clase que contenga un int, un constructor que inicialice el int con su argumento, y una función print() que muestre por pantalla el int. Cree ahora una segunda clase que contenga un objeto estático de la primera. Añada un método estático que llame a la función print() del objeto estático. Pruebe su clase en main().
Cree una clase que contenga un array estático de int constante y otro no constante. Escriba métodos estáticos que impriman los arrays. Experimente con su clase en main().
Cree una clase que contenga un string, con un constructor que inicialice el string a partir de su argumento, y una función print() que imprima el string. Cree otra clase que contenga arrays estáticos, tanto constantes como no constantes, de objetos de la primera clase, y métodos estáticos para imprimir dichos arrays. Experimente con la segunda clase en main().
Cree una struct que contenga un int y un constructor por defecto que inicialice el int a cero. Haga esa struct local a una función. Dentro de dicha función, cree un array de objetos de su struct y demuestre que cada int del array ha sido inicializado a cero automáticamente.
Cree una clase que represente una conexión a impresora, y que sólo le permita tener una impresora.
En un fichero de cabecera, cree una clase Mirror que contiene dos atributos: un puntero a un objeto Mirror y un bool. Déle dos constructores: el constructor por defecto inicializa el bool a true y el puntero a Mirror a cero. El segundo constructor toma como argumento un puntero a un objeto Mirror, que asigna al puntero interno del objeto; pone el bool a false. Añada un método test(): si el puntero del objeto es distinto de cero, devuelve el valor de test() llamado a través del puntero. Si el puntero es cero, devuelve el bool. Cree ahora cinco ficheros cpp, cada uno incluyendo la cabecera Mirror. El primer fichero cpp define un objeto Mirror global utilizando el constructor por defecto. El segundo fichero declara el objeto del primer fichero como extern, y define un objeto Mirror global utilizando el segundo constructor, con un puntero al primer objeto. Siga haciendo lo mismo hasta que llegue al último fichero, que también contendrá una definición de objeto global. En este fichero, main() debe llamar a la función test() e informar del resultado. Si el resultado es true, encuentre la forma de cambiar el orden de enlazado de su enlazador y cámbielo hasta que el resultado sea false.
Repare el problema del Ejercicio 32 utilizando la técnica uno mostrada en este libro.
Repare el problema del Ejercicio 32 utilizando la técnica dos mostrada en este libro.
Sin incluir ningún fichero de cabecera, declare la función puts() de la Librería Estándar de C. Llame a esa función desde main().