Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO Pensar en C++ (Volumen 1) - Grupo ARCO

arco.esi.uclm.es
from arco.esi.uclm.es More from this publisher
13.01.2015 Views

✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 480 — #518 ✐ Capítulo 16. Introducción a las Plantillas require(top < ssize, "Too many push()es"); stack[top++] = i; } int pop() { require(top > 0, "Too many pop()s"); return stack[--top]; } }; int main() { IntStack is; // Add some Fibonacci numbers, for interest: for(int i = 0; i < 20; i++) is.push(fibonacci(i)); // Pop & print them: for(int k = 0; k < 20; k++) cout

✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 481 — #519 ✐ 16.2. Un vistazo a las plantillas Esta es una implementación bastante eficiente, porque nunca se generan los números más de una vez. Se usa un array static de int, y se basa en el hecho de que el compilador inicializará el array estático a cero. El primer bucle for mueve el índice i a la primera posición del array que sea cero, entonces un bucle while añade números Fibonacci al array hasta que se alcance el elemento deseado. Hay que hacer notar que si los números Fibonacci hasta el elemento n ya están inicializados, entonces también se salta el bucle while. 16.1.1. La necesidad de los contenedores Obviamente, una pila de enteros no es una herramienta crucial. La necesidad real de los contenedores viene cuando se empizan a crear objetos en el montón (heap) usando new y se destruyen con delete. En un problema general de programación no se saben cuantos objetos van a ser necesarios cuando se está escribiendo el programa. Por ejemplo, en un sistema de control de tráfico aéreo no se quiere limitar el número de aviones que el sistema pueda gestionar. No puede ser que el programa se aborte sólo porque se excede algún número. En un sistema de diseño asistido por computadora, se están manejando montones de formas, pero únicamente el usuario determina (en tiempo de ejecución) cuantas formas serán necesarias. Una vez apreciemos estas tendencias, se descubrirán montones de ejemplos en otras situaciones de programación. Los programadores de C que dependen de la memoria virtual para manejar su "gestión de memoria" encuentran a menudo como perturbantentes las ideas del new, delete y de los contenedores de clases. Aparentemente, una práctica en C es crear un enorme array global, más grande que cualquier cosa que el programa parezca necesitar. Para esto no es necesario pensar demasiado (o hay que meterse en el uso de malloc() y free()), pero se producen programas que no se pueden portar bien y que esconden sutiles errores. Además, si se crea un enorme array global de objetos en C++, la sobrecarga de los constructores y de los destructores pueden enlentecer las cosas de forma significativa. La aproximación de C++ funciona mucho mejor: Cuando se necesite un objeto, se crea con new, y se pone su puntero en un contenedor. Más tarde, se saca y se hace algo con él. De esta forma, sólo se crean los objetos cuando sea necesario. Y normalmente no se dan todas las condiciones para la inicialización al principio del programa. new permite esperar hasta que suceda algo en el entorno para poder crear el objeto. Así, en la situación más común, se creará un contenedor que almacene los punteros de algunos objetos de interés. Se crearán esos objetos usando new y se pondrá el puntero resultante en el contenedor (potencialmete haciendo upcasting en el proceso), más tarde el objeto se puede recuperar cuando sea necesario. Esta técnica produce el tipo de programas más flexible y general. 16.2. Un vistazo a las plantillas Ahora surge un nuevo problema. Tenemos un IntStack, que maneja enteros. Pero queremos una pila que maneje formas, o flotas de aviones, o plantas o cualquier otra cosa. Reinventar el código fuente cada vez no parece una aproximación muy inteligente con un lenguaje que propugna la reutilización. Debe haber un camino mejor. Hay tres técnicas para reutilizar código en esta situación: el modo de C, presen- 481 ✐ ✐ ✐ ✐

✐<br />

✐<br />

✐<br />

“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 480 — #518<br />

✐<br />

Capítulo 16. Introducción a las Plantillas<br />

require(top < ssize, "Too many push()es");<br />

stack[top++] = i;<br />

}<br />

int pop() {<br />

require(top > 0, "Too many pop()s");<br />

return stack[--top];<br />

}<br />

};<br />

int main() {<br />

IntStack is;<br />

// Add some Fibonacci numbers, for interest:<br />

for(int i = 0; i < 20; i++)<br />

is.push(fibonacci(i));<br />

// Pop & print them:<br />

for(int k = 0; k < 20; k++)<br />

cout

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!