13.01.2015 Views

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

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

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

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

✐<br />

✐<br />

✐<br />

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

✐<br />

15.12. Downcasting<br />

Para simplificar sólo se ha sobrecargado el operator*. El objetivo es ser capaz de<br />

multiplicar dos objetos Math cualquiera y producir el resultado deseado - hay que<br />

darse cu<strong>en</strong>ta que multiplicar una matriz por un vector es una operación totalm<strong>en</strong>te<br />

distinta a la de multiplicar un vector por una matriz.<br />

El problema es que, <strong>en</strong> el main(), la expresión m1 * m2 conti<strong>en</strong>e dos refer<strong>en</strong>cias<br />

Math, y son dos objetos de tipo desconocido. Una función virtual es sólo capaz de<br />

hacer una única llamada - es decir, determinar el tipo de un único objeto. Para determinar<br />

ambos tipos <strong>en</strong> este ejemplo se usa una técnica conocida como despachado<br />

múltiple (multiple dispatching), donde lo que parece ser una única llamada a una función<br />

virtual se convierte <strong>en</strong> una segunda llamada a una función virtual. Cuando la<br />

segunda llamada se ha ejecutado, ya se han determinado ambos tipos de objetos y<br />

se puede ejecutar la actividad de forma correcta. En un principio no es transparante,<br />

pero después de un rato mirando el código empieza a cobrar s<strong>en</strong>tido. Esta materia es<br />

tratada con más profundidad <strong>en</strong> el capítulo de los patrones de diseño <strong>en</strong> el Volum<strong>en</strong><br />

2 que se puede bajar de >www.BruceEckel.com.<br />

15.12. Downcasting<br />

Como se puede adivinar, desde el mom<strong>en</strong>to que existe algo conocido como upcasting<br />

- mover <strong>en</strong> s<strong>en</strong>tido asc<strong>en</strong>d<strong>en</strong>te por una jerarquía de her<strong>en</strong>cia - debe existir el<br />

downcasting para mover <strong>en</strong> s<strong>en</strong>tido desc<strong>en</strong>d<strong>en</strong>te <strong>en</strong> una jerarquía. Pero el upcasting<br />

es s<strong>en</strong>cillo porque al movernos <strong>en</strong> s<strong>en</strong>tido asc<strong>en</strong>d<strong>en</strong>te <strong>en</strong> la jerarquía de clases siempre<br />

convergemos <strong>en</strong> clases más g<strong>en</strong>erales. Es decir, cuando se hace un upcast siempre<br />

se está <strong>en</strong> una clase claram<strong>en</strong>te derivada de un asc<strong>en</strong>d<strong>en</strong>te (normalm<strong>en</strong>te solo uno,<br />

excepto <strong>en</strong> el caso de her<strong>en</strong>cia múltiple) pero cuando se hace downcast hay normalm<strong>en</strong>te<br />

varias posibilidades a las que amoldarse. Mas concretam<strong>en</strong>te, un Circulo es<br />

un tipo de Figura (que sería su upcast), pero si se int<strong>en</strong>ta hacer un downcast de una<br />

Figura podría ser un Circulo, un Cuadrado, un Triángulo, etc. El problema<br />

es <strong>en</strong>contrar un modo seguro de hacer downcast (aunque es incluso más importante<br />

preguntarse por qué se está usando downcasting <strong>en</strong> vez de usar el polimorfismo para<br />

que adivine automáticam<strong>en</strong>te el tipo correcto. En el Volum<strong>en</strong> 2 de este libro se trata<br />

como evitar el downcasting.<br />

<strong>C++</strong> proporciona un moldeado explícito especial (introducido <strong>en</strong> el capítulo 3)<br />

llamado "moldeado dinámico" (dynamic_cast) que es una operación segura. Cuando<br />

se usa moldeado dinámico para int<strong>en</strong>tar hacer un molde a un tipo <strong>en</strong> concreto, el valor<br />

de retorno será un puntero al tipo deseado sólo si el molde es adecuado y ti<strong>en</strong>e éxito,<br />

de otra forma devuelve cero para indicar que no es del tipo correcto. Aquí t<strong>en</strong>emos<br />

un ejemplo mínimo:<br />

//: C15:DynamicCast.cpp<br />

#include <br />

using namespace std;<br />

class Pet { public: virtual ~Pet(){}};<br />

class Dog : public Pet {};<br />

class Cat : public Pet {};<br />

int main() {<br />

Pet* b = new Cat; // Upcast<br />

// Try to cast it to Dog*:<br />

471<br />

✐<br />

✐<br />

✐<br />

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

Saved successfully!

Ooh no, something went wrong!