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.
Implemente la jerarquía de herencia del diagrama de OShape de este capítulo.
Modifique el resultado del Ejercicio 1 del Capítulo 15 para usar la Stack y el iterator en TStack2.h en vez de un array de punteros a Shape. Añada destructores a la jerarquía de clases para que se pueda ver que los objetos Shape se destruyen cuando la Stack sale del ámbito.
Modifique TPStash.h para que el valor de incremento usado por inflate() pueda ser cambiado durante la vida de un objeto contenedor particular.
Modifique TPStash.h para que el valor de incremento usado por inflate() se ajuste automáticamente para reducir el número de veces que hay que llamarla. Por ejemplo, cada vez que se llama podría doblar el valor de incremento para su uso en la siguiente llamada. Demuestre la funcionalidad informando cada vez que se llama a inflate(), y escriba código de prueba en main().
Convierta en plantilla la función fibonacci() sobre el tipo de valor que produce (para que pueda generar long, float, etc. en vez de sólo int).
Usando el vector de la Librería Estándar de C++ como implementación subyacente, cree una clase plantilla Set que acepte sólo uno de cada tipo de objeto que se introduzca en ella. Cree una clase iterador anidada que soporte el concepto de «centinela final» de este capítulo. Escriba código de prueba para su Set en el main(), y después sustitúyalo por la plantilla set de la Librería Estándar de C++ para comprobar que el comportamiento es correcto.
Modifique AutoCounter.h para que pueda ser usado como un objeto miembro dentro de cualquier clase cuya creación y destrucción quiera seguir. Añada un miembro string para que contenga el nombre de la clase. Pruebe esta herramienta dentro de una clase propia.
Cree una versión de OwnerStack.h que use un vector de la Librería Estándar de C++ como su implementación subyacente. Puede que necesite consultar algunas de las funciones miembro de vector para poder hacerlo (o simplemente mirar el fichero de cabecera <vector>).
Modifique ValueStack.h para que pueda expandirse dinámicamente cuando se introduzcan más objetos con push() y se quede sin espacio. Cambie ValueStackTest.cpp para comprobar su nueva funcionalidad.
Repita el ejercicio 9 pero use el vector de la Librería Estándar de C++ como la implementación interna de ValueStack. Note lo mucho más sencillo que resulta.
Modifique ValueStackTest.cpp para que use un vector de la Librería Estándar de C++ en vez de un Stack en el main(). Observe el comportamiento en tiempo de ejecución: ¿crea automáticamente el vector un montón de objetos por defecto cuando se crea?
Modifique TStack2.h para que use un vector de la Librería Estándar de C++ como su implementación subyacente. Asegúrese de que no cambia la interfaz, para que TStack2Test.cpp funcione sin cambios.
Repita el Ejercicio 12 usando una stack de la Librería Estándar de C++ en vez de un vector (puede que necesite buscar información sobre stack, o rebuscar en el fichero de cabecera <stack>).
Modifique TPStash2.h para que use un vector de la Librería Estándar de C++ como su implementación subyacente. Asegúrese de que no cambia la interfaz, para que TPStash2Test.cpp funcione sin cambios.
En IterIntStack.cpp, modifique IntStackIter para darle un constructor de «centinela final», y añada el operator== y el operator!=. En el main(), use un iterador para moverse a través de los elementos del contenedor hasta que llegue al centinela final.
Usando TStack2.h, TPStash2.h y Shape.h, instancie contenedores Stack y PStash para Shape*, rellene cada uno con un surtido de punteros a Shape convertidos mediante upcast, y después use iteradores para moverse a través de cada contenedor y llame a draw() para cada objeto.
Convierta en plantilla la clase Int de TPStash2Test.cpp para que pueda contener cualquier tipo de objeto (siéntase libre de cambiar el nombre de la clase por algo más apropiado).
Convierta en plantilla la clase IntArray de IostreamOperatorOverloading.cpp del Capítulo 12, parametrizando tanto el tipo de objeto contenido como el tamaño del array interno.
Convierta ObjContainer en NestedSmartPointer.cpp del Capítulo 12 en una plantilla. Compruébelo con dos clases diferentes.
Modifique C15:OStack.h y C15:OStackTest.cpp convirtiendo en plantilla class Stack para que herede automáticamente (con herencia múltiple) de la clase contenida y de Object. La Stack generada debe aceptar y producir sólo punteros del tipo contenido.
Repita el ejercicio 20 usando vector en vez de Stack.
Herede una clase StringVector de vector<void*> y redefina las funciones miembro push_back() y operator[] para que acepten y produzcan únicamente string* (y realicen el moldeado adecuado). Ahora cree una plantilla que genere automáticamente una clase contenedora que haga lo mismo para punteros de cualquier tipo. Esta técnica se usa a menudo para reducir el exceso de código producido por demasiadas instanciaciones de plantillas.
En TPStash2.h, añada y compruebe un operator- para PStash::iterator, siguiendo la lógica de operator+.
En Drawing.cpp, añada y compruebe una plantilla de función que llame a funciones miembro erase().
(Avanzado) Modifique la clase Stack en TStack2.h para permitir una granularidad total de la propiedad: añada una bandera a cada enlace indicando si el enlace posee el objeto al que apunta, y dé soporte a esta información en la función push() y en el destructor. Añada funciones miembro para leer y cambiar la propiedad de cada enlace.
(Avanzado) Modifique PointerToMemberOperator.cpp del Capítulo 12 para que la FunctionObject y el operator->* se conviertan en plantillas para que funcionen con cualquier tipo de retorno (para operator->*, tendrá que usar plantillas miembro, descritas en el Volumen 2). Añada y pruebe el soporte para cero, uno y dos argumentos en las funciones miembro de Dog.