16.10. Ejercicios

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.

  1. Implemente la jerarquía de herencia del diagrama de OShape de este capítulo.

  2. 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 han sido destruidos cuando la Stack se sale del ámbito.

  3. Modifique TPStash.h para que el valor de incremento usado por inflate() pueda ser cambiado durante la vida de un objeto contenedor particular.

  4. Modifique TPStash.h para que el valor de incremento usado por inflate() automáticamente cambie de tamaño para que reduzca el número de veces que debe ser llamado. Por ejemplo, cada vez que se llama podría doblar el valor de incremento para su uso en la siguiente llamada. Demuestre la funcionalidad mostrando cada vez que se llama a inflate(), y escriba código de prueba en main().

  5. Convierta en plantilla la función de fibonacci() con los tipos que puede producir (puede generar long, float, etc. en vez de sólo int).

  6. Usar el vector de la STL como implementación subyacente, para crear una platilla Set que acepte solo uno de cada tipo de objeto que se aloje en él. Cree un iterador anidado que soporte el concepto de "marcador final" de este capítulo. Escriba código de prueba para el Set en el main(), y entonces sustituyalo por la plantilla set de la STL para comprobar que el comportamiento es correcto.

  7. Modifique AutoCounter.h para que pueda ser usado como un objeto miembro dentro de cualquier clase cuya creación y destrucción quiera comprobar. Añada un miembro string para que contenga el nombre de la clase. Compruebe esta herramienta dentro una clase suya.

  8. Cree una versión de OwnerStack.h que use un vector de la Librería Estándar de C++ como su implementación subyacente. Será necesario conocer algunas de las funciones miembro de vector para poder hacerlo (sólo hay que mirar en el archivo cabecera <vector>).

  9. Modifique ValueStack.h para que pueda expandirse dinámicamente según se introduzcan más objetos y se quede sin espacio. Cambie ValueStackTest.cpp para comprobar su nueva funcionalidad.

  10. Repita el ejercicio 9 pero use el vector de la STL como la implementación interna de ValueStack. Note lo sencillo que es.

  11. Modifique ValueStackTest.cpp para que use un vector de la STL en vez de un Stack en el main(). Dése cuenta del comportamiento en tiempo de ejecución: ¿Se genera un grupo de objetos por defecto cuando se crea el vector?

  12. Modifique TStack2.h para que use un vector de la STL. Asegurese de que no cambia la interfaz, para que TStack2Test.cpp funcione sin cambiarse.

  13. Repita el Ejercicio 12 usando una stack de la Librería Estándar de C++ en vez de un vector.

  14. Modifique TPStash2.h para que use un vector de la STL como su implementación interna. Asegurese que no cambia la interfaz, por lo que TPStash2Test.cpp funciona sin modificarse.

  15. En IterIntStack.cpp, modifique IntStackIter para darle un constructor de «marcador 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 se encuentre el marcador.

  16. Use TStack2.h, TPSTash2.h, y Shape.h, instancie los contenedores PStash y Stack para que contenga Shape*, rellene cada uno con punteros a Shape, entonces use iteradores para moverse a través de cada contenedor y llame a draw() para cada objeto.

  17. Cree una plantilla en la clase Int para que pueda alojar cualquier tipo de objetos (Siéntase libre de cambiar el nombre de la clase a algo más apropiado).

  18. Cree una plantilla de la clase IntArray en IostreamOperatorOverloading.cpp del capítulo 12, introduzca en plantilla ambos tipos de objetos que están contenidos y el tamaño del array interno

  19. Convierta ObjContainer en NestedSmartPointer.cpp del Capítulo 12 en una plantilla. Compruebelo con dos clases diferentes.

  20. Modifique C15:OStack.h y C15:OStackTest.cpp consiguiendo que class Stack pueda tener múltiple herencia automáticamente de la clase contenida y de Object. La Stack contenida debe aceptar y producir sólo punteros del tipo contenido.

  21. Repita el ejercicio 20 usando vector en vez de Stack.

  22. Herede una clase StringVector de vector<void> y redefina las funciones miembro push_back() y el operator[] para que acepten y produzcan únicamente string* (y realizen el moldeado adecuado). Ahora creee una plantilla que haga automáticamente lo mismo a una clase contenedora para punteros de cualquier tipo. Esta técnica es a menudo usada para reducir el código producido por muchas instanciaciones de templates.

  23. En TPStash2.h, añada y compruebe un operator- para PStash::iterator, siguiendo la lógica de operator+.

  24. En Drawing.cpp, añada y compruebe una plantilla de función que llame a funciones miembro erase().

  25. (Avanzado) Modifique la clase Stack en TStack2.h para permitir una granularidad de la propiedad: Añada una bandera para cada enlace indicando si el enlace posee el objeto al que apunta, y de soporte a esta información la función push() y en el destructor. Añada funciones miembro para leer y cambiar la propiedad de cada enlace.

  26. (Avanzado) Modifique PointerToMemberOperator.cpp del Capítulo 12 para que la FunctionObject y el operator->* sean convertidos en plantillas para que funcionen con cualquier tipo de retorno (para operator->*, tendrá que usar plantillas miembro descritas en el Volumen 2). Añada soporte y compruebe para cero, uno y dos argumentos en las funciones miembro Dog.