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 430 — #468 ✐ Capítulo 14. Herencia y Composición El fichero es idéntico a InheritStack.cpp, excepto que un objeto Stack es alojado en StringStack y se utilizan las funciones miembros para llamarlo. No se consume tiempo o espacio porque el subobjeto tiene el mismo tamaño y todas las comprobaciones de tipos han ocurrido en tiempo de compilación. Sin embargo, esto tiende a confusión, podría también utilizar la herencia privada para expresar "implementado en términos de". Esto también resolvería el problema de forma adecuada. Un punto importante es cuando la herencia múltiple puede ser garantizada. En este caso, si observa un diseño en que la composición pueda utilizarse en vez de la herencia, debe eliminar la necesidad de utilizar herencia múltiple. 14.10.4. FIXME Upcasting de punteros y referencias En Instrument.cpp, la conversión ocurre durante la llamada a la función - un objeto Wind fuera de la función se toma como referencia y se convierte en una referencia Instrument dentro de la función. La conversión puede también ocurrir durante una asignación a un puntero o una referencia. Wind w; Instrument* ip = &w; // Upcast Instrument& ir = w; // Upcast Como en la llamada a la función, ninguno de estos casos requiere una conversión explicita. 14.10.5. Una crisis Por supuesto, cualquier conversión pierde la información del tipo sobre el objeto. Si dice Wind w; Instrument* ip = &w; el compilador puede utilizar ip solo como un puntero a Instrumento y nada mas. Esto es, éste no puede conocer que ip realmente esta apuntando a un objeto Wind. Entonces cuando llame a la función miembro play() diciendo ip->play(middleC); el compilador solo puede conocer que la llamada a play() es de un puntero a Instrument y llamara a la versión de la clase base Instrument::play() en vez de lo que debería hacer, que es llamar a Wind::play(). Así, no conseguirá una conducta adecuada. esto es un problema importante; es resulto en el Capitulo 15, introducción al tercer pilar de la programación orientada a objetos: poliformismo (implementado en C++ con funciones virtuales). 430 ✐ ✐ ✐ ✐

✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 431 — #469 ✐ 14.11. Resumen 14.11. Resumen Herencia y composición le permiten crear nuevos tipos desde tipos existentes y ambos incluyen subobjetos de tipos existentes dentro del nuevo tipo. Sin embargo, normalmente, utilizara la composición para reutilizar tipos existentes como parte de la capa de implementación de un nuevo tipo y la herencia cuando desea forzar al nuevo tipo a ser del mismo tipo que la clase base (la equivalencia de tipos garantiza la equivalencia de la interfaz). Como las clases derivadas tienen el interfaz de la clase base, esta puede ser convertidas a la base, lo cual es crítico para el poliformismo como verá el Capítulo 15. Aunque la reutilización de código a través de la composición y la herencia es muy útil para el desarrollo rápido de proyectos, generalmente deseara rediseñar su jerarquía de clases antes de permitir a otros programadores dependan de ella. Su objetivo es crear una jerarquía en que cada clase tenga un uso especifico y sin ser demasiado grande (esforzándose más en la funcionalidad que en la dificultad de la reutilización...), ni pequeña, (no se podrá usar por si mismo o sin añadir funcionalidad). 14.12. 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. Modificar Car.cpp para que herede desde una clase llamada Vehicle, colocando correctamente las funciones miembro en Vehicle (esto es, añadir algunas funciones miembro). Añada un constructor (no el de por defecto) a Vehicle, que debe ser llamado desde dentro del constructor Car 2. Crear dos clases, A y B, con constructor por defectos notificándose ellos mismos. Una nueva clase llamada C que hereda de A, y cree un objeto miembro B dentro de C, pero no cree un constructor para C. Cree un objeto de la clase C y observe los resultados. 3. Crear una jerarquía de clases de tres niveles con constructores por defecto y con destructores, ambos notificándose utilizando cout. Verificar que el objeto más alto de la jerarquía, los tres constructores y destructores son ejecutados automáticamente. Explicar el orden en que han sido realizados. 4. Modificar Combined.cpp para añadir otro nivel de herencia y un nuevo objeto miembro. Añadir el código para mostrar cuando los constructores y destructores son ejecutados. 5. En Combined.cpp, crear una clase D que herede de B y que tenga un objeto miembro de la clase C. Añadir el código para mostrar cuando los constructores y los destructores son ejecutados. 6. Modificar Order.cpp para añadir otro nivel de herencia Derived3 con objetos miembro de la clase Member4 y Member5. Compruebe la salida del programa. 7. En NameHidding.cpp, verificar que Derived2, Derived3 y Derived4, ninguna versión de la clase base de f() esta disponible. 431 ✐ ✐ ✐ ✐

✐<br />

✐<br />

✐<br />

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

✐<br />

14.11. Resum<strong>en</strong><br />

14.11. Resum<strong>en</strong><br />

Her<strong>en</strong>cia y composición le permit<strong>en</strong> crear nuevos tipos desde tipos exist<strong>en</strong>tes y<br />

ambos incluy<strong>en</strong> subobjetos de tipos exist<strong>en</strong>tes d<strong>en</strong>tro del nuevo tipo. Sin embargo,<br />

normalm<strong>en</strong>te, utilizara la composición para reutilizar tipos exist<strong>en</strong>tes como parte de<br />

la capa de implem<strong>en</strong>tación de un nuevo tipo y la her<strong>en</strong>cia cuando desea forzar al<br />

nuevo tipo a ser del mismo tipo que la clase base (la equival<strong>en</strong>cia de tipos garantiza<br />

la equival<strong>en</strong>cia de la interfaz). Como las clases derivadas ti<strong>en</strong><strong>en</strong> el interfaz de la clase<br />

base, esta puede ser convertidas a la base, lo cual es crítico para el poliformismo<br />

como verá el Capítulo 15.<br />

Aunque la reutilización de código a través de la composición y la her<strong>en</strong>cia es<br />

muy útil para el desarrollo rápido de proyectos, g<strong>en</strong>eralm<strong>en</strong>te deseara rediseñar su<br />

jerarquía de clases antes de permitir a otros programadores dep<strong>en</strong>dan de ella. Su<br />

objetivo es crear una jerarquía <strong>en</strong> que cada clase t<strong>en</strong>ga un uso especifico y sin ser<br />

demasiado grande (esforzándose más <strong>en</strong> la funcionalidad que <strong>en</strong> la dificultad de la<br />

reutilización...), ni pequeña, (no se podrá usar por si mismo o sin añadir funcionalidad).<br />

14.12. Ejercicios<br />

Las soluciones a los ejercicios se pued<strong>en</strong> <strong>en</strong>contrar <strong>en</strong> el docum<strong>en</strong>to electrónico<br />

titulado «The Thinking in <strong>C++</strong> Annotated Solution Guide», disponible por poco<br />

dinero <strong>en</strong> www.BruceEckel.com.<br />

1. Modificar Car.cpp para que herede desde una clase llamada Vehicle, colocando<br />

correctam<strong>en</strong>te las funciones miembro <strong>en</strong> Vehicle (esto es, añadir algunas funciones<br />

miembro). Añada un constructor (no el de por defecto) a Vehicle, que<br />

debe ser llamado desde d<strong>en</strong>tro del constructor Car<br />

2. Crear dos clases, A y B, con constructor por defectos notificándose ellos mismos.<br />

Una nueva clase llamada C que hereda de A, y cree un objeto miembro B<br />

d<strong>en</strong>tro de C, pero no cree un constructor para C. Cree un objeto de la clase C y<br />

observe los resultados.<br />

3. Crear una jerarquía de clases de tres niveles con constructores por defecto y<br />

con destructores, ambos notificándose utilizando cout. Verificar que el objeto<br />

más alto de la jerarquía, los tres constructores y destructores son ejecutados<br />

automáticam<strong>en</strong>te. Explicar el ord<strong>en</strong> <strong>en</strong> que han sido realizados.<br />

4. Modificar Combined.cpp para añadir otro nivel de her<strong>en</strong>cia y un nuevo objeto<br />

miembro. Añadir el código para mostrar cuando los constructores y destructores<br />

son ejecutados.<br />

5. En Combined.cpp, crear una clase D que herede de B y que t<strong>en</strong>ga un objeto<br />

miembro de la clase C. Añadir el código para mostrar cuando los constructores<br />

y los destructores son ejecutados.<br />

6. Modificar Order.cpp para añadir otro nivel de her<strong>en</strong>cia Derived3 con objetos<br />

miembro de la clase Member4 y Member5. Compruebe la salida del programa.<br />

7. En NameHidding.cpp, verificar que Derived2, Derived3 y Derived4, ninguna<br />

versión de la clase base de f() esta disponible.<br />

431<br />

✐<br />

✐<br />

✐<br />

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

Saved successfully!

Ooh no, something went wrong!