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 454 — #492<br />

✐<br />

Capítulo 15. Polimorfismo y Funciones virtuales<br />

Figura 15.4: Una nueva función virtual<br />

Hay que hacer notar, que el compilador mapea la dirección de speak() <strong>en</strong> exactam<strong>en</strong>te<br />

el mismo lugar tanto <strong>en</strong> la VTABLE de Dog como <strong>en</strong> la de Pet. De igual<br />

forma, si una clase Pug heredara de Dog, su versión de sit() ocuparía su lugar <strong>en</strong><br />

la VTABLE <strong>en</strong> la misma posición que <strong>en</strong> Dog. Esto es debido a que el compilador<br />

g<strong>en</strong>era un código que usa un simple desplazami<strong>en</strong>to numérico <strong>en</strong> la VTABLE para<br />

seleccionar una función virtual, como se vio con el ejemplo <strong>en</strong> l<strong>en</strong>guaje <strong>en</strong>samblador.<br />

Sin importar el subtipo <strong>en</strong> concreto del objeto, su VTABLE está colocada de la misma<br />

forma por lo que llamar a una función virtual se hará siempre del mismo modo.<br />

En este caso, sin embargo, el compilador está trabajando sólo con un puntero a<br />

un objeto de la clase base. La clase base ti<strong>en</strong>e únicam<strong>en</strong>te las funciones speak()<br />

y name(), por lo que son a las únicas funciones a las que el compilador permitirá<br />

acceder. ¿Cómo es posible saber que se está trabajando con un objeto Dog si sólo<br />

hay un puntero a un objeto de la clase base El puntero podría apuntar a algún<br />

otro tipo, que no t<strong>en</strong>ga una función sit(). En este punto, puede o no t<strong>en</strong>er otra<br />

dirección a función <strong>en</strong> la VTABLE, pero <strong>en</strong> cualquiera de los casos, hacer una llamada<br />

a una función virtual de esa VTABLE no es lo que se desea hacer. De modo que el<br />

compilador hace su trabajo impidi<strong>en</strong>do hacer llamadas virtuales a funciones que<br />

sólo exist<strong>en</strong> <strong>en</strong> las clases derivadas.<br />

Hay algunos poco comunes casos <strong>en</strong> los cuales se sabe que el puntero actualm<strong>en</strong>te<br />

apunta al objeto de una subclase específica. Si se quiere hacer una llamada a una<br />

función que sólo exista <strong>en</strong> esa subclase, <strong>en</strong>tonces hay que hacer un molde (cast) del<br />

puntero. Se puede quitar el m<strong>en</strong>saje de error producido por el anterior programa<br />

con:<br />

((Dog *) p[1])->sit()<br />

Aquí, parece saberse que p[1] apunta a un objeto Dog, pero <strong>en</strong> g<strong>en</strong>eral no se<br />

sabe. Si el problema consiste <strong>en</strong> averiguar el tipo exacto de todos los objetos, hay<br />

que volver a p<strong>en</strong>sar porque posiblem<strong>en</strong>te no se estén usando las funciones virtuales<br />

de forma apropiada. Sin embargo, hay algunas situaciones <strong>en</strong> las cuales el diseño<br />

funciona mejor (o no hay otra elección) si se conoce el tipo exacto de todos los objetos,<br />

por ejemplo aquellos incluidos <strong>en</strong> un cont<strong>en</strong>edor g<strong>en</strong>érico. Este es el problema de la<br />

run time type id<strong>en</strong>tification o RTTI (id<strong>en</strong>tificación de tipos <strong>en</strong> tiempo de ejecución).<br />

RTTI sirve para moldear un puntero de una clase base y "bajarlo" a un puntero de<br />

una clase derivada ("arriba" y "abajo", <strong>en</strong> inglés "up" y "down" respectivam<strong>en</strong>te, se<br />

refier<strong>en</strong> al típico diagrama de clases, con la clase base arriba). Hacer el molde hacia<br />

arriba (upcast) funciona de forma automática, sin coacciones, debido a que es completam<strong>en</strong>te<br />

seguro. Hacer el molde <strong>en</strong> s<strong>en</strong>tido desc<strong>en</strong>d<strong>en</strong>te (downcast) es inseguro<br />

porque no hay información <strong>en</strong> tiempo de compilación sobre los tipos actuales, por lo<br />

que hay que saber exactam<strong>en</strong>te el tipo al que pert<strong>en</strong>ece. Si se hace un molde al tipo<br />

454<br />

✐<br />

✐<br />

✐<br />

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

Saved successfully!

Ooh no, something went wrong!