Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
✐<br />
✐<br />
✐<br />
“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 414 — #452<br />
✐<br />
Capítulo 14. Her<strong>en</strong>cia y Composición<br />
orpr<strong>en</strong>dido ¡este mecanismo de comprobación de tipos seguro es gratuito, <strong>en</strong><br />
push(), peek() y pop! Al compilador se le proporciona información extra acerca de<br />
los tipos y éste lo utiliza <strong>en</strong> tiempo de compilación, pero las funciones son inline y<br />
no es necesario ningún código extra.<br />
La ocultación de nombres <strong>en</strong>tra <strong>en</strong> acción <strong>en</strong> la función push() que ti<strong>en</strong>e la signatura<br />
difer<strong>en</strong>te: la lista de argum<strong>en</strong>tos. Si se tuvies<strong>en</strong> dos versiones de push() <strong>en</strong> la<br />
misma clase, t<strong>en</strong>drían que ser sobrecargadas, pero <strong>en</strong> este caso la sobrecarga no es<br />
lo que deseamos porque todavía permitiría pasar cualquier tipo de puntero a push<br />
como void *. Afortunadam<strong>en</strong>te, <strong>C++</strong> esconde la versión push (void *) <strong>en</strong> la clase base<br />
<strong>en</strong> favor de la nueva versión que es definida <strong>en</strong> la clase derivada, de este modo, solo<br />
se permite utilizar la función push() con punteros a String <strong>en</strong> StringStack.<br />
Ahora podemos asegurar que se conoce exactam<strong>en</strong>te el tipo de objeto que esta<br />
<strong>en</strong> el cont<strong>en</strong>edor, el destructor funcionará correctam<strong>en</strong>te y problema esta resuelto -<br />
o al m<strong>en</strong>os, un parte del procedimi<strong>en</strong>to. Si utiliza push( ) con un puntero a String <strong>en</strong><br />
StringStack, <strong>en</strong>tonces (según el significado de StringStack) también se esta pasando<br />
el puntero a StringStack. Si utiliza pop(), no solo consigue puntero, sino que a la vez<br />
el propietario. Cualquier puntero que se haya dejado <strong>en</strong> StringStack será borrado<br />
cuando el destructor sea invocado. Puesto que siempre son punteros a Strings y la<br />
declaración delete esta funcionando con punteros a String <strong>en</strong> vez de punteros a void,<br />
la destrucción se realiza de forma adecuada y todo funciona correctam<strong>en</strong>te.<br />
Esto es una desv<strong>en</strong>taja: esta clase solo funciona con punteros de cad<strong>en</strong>as. Si se<br />
desea un Stack que funcione con cualquier variedad de objetos, se debe escribir una<br />
nueva versión de la clase que funcione con ese nuevo tipo de objeto. Esto puede<br />
convertirse rápidam<strong>en</strong>te <strong>en</strong> una tarea tediosa, pero finalm<strong>en</strong>te es resulta utilizando<br />
plantillas como se vera <strong>en</strong> el capítulo 16.<br />
Exist<strong>en</strong> consideraciones adicionales sobre este ejemplo: el cambio de la interfaz<br />
<strong>en</strong> Stack <strong>en</strong> el proceso de her<strong>en</strong>cia. Si la interfaz es difer<strong>en</strong>te, <strong>en</strong>tonces StringStack<br />
no es realm<strong>en</strong>te un Stack, y nunca será posible usar de forma correcta un StringStack<br />
como Stack. Esto hace que el uso de la her<strong>en</strong>cia sea cuestionable <strong>en</strong> este punto; si<br />
no se esta creando un StringStack del tipo Stack, <strong>en</strong>tonces, porque hereda de él. Más<br />
adelante, s<strong>en</strong> este mismo capítulo se mostrará una versión más adecuada.<br />
14.5. Funciones que no heredan automáticam<strong>en</strong>te<br />
No todas las funciones son heredadas automáticam<strong>en</strong>te desde la clase base a la<br />
clase derivada. Los constructores y destructores manejan la creación y la destrucción<br />
de un objeto y sólo ellos sab<strong>en</strong> que hacer con los aspectos de un objeto <strong>en</strong> sus<br />
clases particulares y por ello los constructores y destructores inferiores de la jerarquía<br />
deb<strong>en</strong> llamarlos. Así, los constructores y destructores no se heredan y deb<strong>en</strong> ser<br />
creados específicam<strong>en</strong>te <strong>en</strong> cada clase derivada.<br />
Además, operator= tampoco se hereda porque realiza una acción parecida al<br />
constructor. Esto es, sólo porque conoce como asignar todos los miembros de un<br />
objeto, la parte izquierda del = a la parte derecha del otro objeto, no significa que la<br />
asignación t<strong>en</strong>drá el mismo significado después de la her<strong>en</strong>cia.<br />
En la her<strong>en</strong>cia, estas funciones son creadas por el compilador si no son creadas<br />
por usted. (Con constructores, no se pued<strong>en</strong> crear constructores para que el compilador<br />
cree el constructor por defecto y el constructor copia.) Esto fue brevem<strong>en</strong>te<br />
descrito <strong>en</strong> el capítulo 6. Los constructores creados se usan <strong>en</strong> inicialización de sus<br />
miembros y la creación del operator= usa la asignación de los miembros. A continuación,<br />
un ejemplo de las funciones que son creadas por el compilador.<br />
414<br />
✐<br />
✐<br />
✐<br />
✐