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 460 — #498<br />

✐<br />

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

de retorno la función de la clase base es la única razón que hace que esto compile. De<br />

esta forma el acuerdo se cumple totalm<strong>en</strong>te: eats() siempre devuelve un puntero<br />

a PetFood.<br />

Si se pi<strong>en</strong>sa de forma polimórfica lo anterior no parece necesario. ¿Por qué no<br />

simplem<strong>en</strong>te se hac<strong>en</strong> upcast de todos los tipos retornados a PetFood* como lo hace<br />

Bird::eats() Normalm<strong>en</strong>te esa es una bu<strong>en</strong>a solución, pero al final del main()<br />

se puede ver la difer<strong>en</strong>cia: Cat::eats() puede devolver el tipo exacto de PetFood,<br />

mi<strong>en</strong>tras que al valor retornado por Bird::eats() hay que hacerle un downcast<br />

al tipo exacto.<br />

Devolver el tipo exacto es un poco más g<strong>en</strong>eral y además no pierde la información<br />

específica de tipo debida al upcast automático. Sin embargo, devolver un tipo de<br />

la clase base g<strong>en</strong>eralm<strong>en</strong>te resuelve el problema por lo que esto es una característica<br />

bastante específica.<br />

15.10. funciones virtuales y constructores<br />

Cuando se crea un objeto que conti<strong>en</strong>e funciones virtuales, su VPTR debe ser inicializado<br />

para apuntar a la correcta VTABLE. Esto debe ser hecho antes de que exista<br />

la oportunidad de llamar a una función virtual. Como se puede adivinar, debido a<br />

que el constructor ti<strong>en</strong>e el trabajo de traer a la exist<strong>en</strong>cia al objeto, también será trabajo<br />

del constructor inicializar el VPTR. El compilador de forma secreta añade código<br />

al principio del constructor para inicializar el VPTR. Y como se describe <strong>en</strong> el capítulo<br />

14, si no se crea un constructor de una clase de forma explícita, el compilador<br />

g<strong>en</strong>era uno de forma automática. Si la clase ti<strong>en</strong>e funciones virtuales, el constructor<br />

incluirá el código apropidado para la inicialización del VPTR. Esto ti<strong>en</strong>e varias<br />

consecu<strong>en</strong>cias.<br />

La primera concierne a la efici<strong>en</strong>cia. La razón de que existan funciones inline<br />

es reducir la sobrecarga que produce llamar a funciones pequeñas. Si <strong>C++</strong> no<br />

proporciona funciones inline, el preprocesador debe ser usado para crear estas<br />

"macros". Sin embargo, el preprocesador no ti<strong>en</strong>e los conceptos de accesos o clases,<br />

y además no puede ser usado para crear macros con funciones miembro. Además,<br />

con los constructores que deb<strong>en</strong> t<strong>en</strong>er código oculto insertado por el compilador, una<br />

macro del preprocesador no funcionaría del todo.<br />

Hay que estar precavidos cuando se estén buscando agujeros de efici<strong>en</strong>cia porque<br />

el compilador está insertando código oculto <strong>en</strong> los constructores. No sólo hay que<br />

inicializar el VPTR, también hay que comprobar el valor de this (<strong>en</strong> caso de que el<br />

operador new devuelva cero), y llamar al constructor de la clase base. Todo junto, éste<br />

código puede t<strong>en</strong>er cierto impacto cuando se p<strong>en</strong>saba que era una simple función<br />

inline. En particular, el tamaño del constructor puede aplastar al ahorro que se<br />

consigue al reducir la sobrecarga <strong>en</strong> las llamadas. Si se hac<strong>en</strong> un monton de llamadas<br />

a constructores inline, el tamaño del código puede crecer sin ningún b<strong>en</strong>eficio <strong>en</strong> la<br />

velocidad.<br />

Cuando esté afinando el código recuerde considerar el quitar los constructores <strong>en</strong><br />

línea.<br />

15.10.1. Ord<strong>en</strong> de las llamadas a los constructores<br />

La segunda faceta interesante de los constructores y las funciones virtuales ti<strong>en</strong>e<br />

que ver con el ord<strong>en</strong> de las llamadas a los constructores y el modo <strong>en</strong> que las<br />

llamadas virtuales se hac<strong>en</strong> d<strong>en</strong>tro de los constructores.<br />

460<br />

✐<br />

✐<br />

✐<br />

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

Saved successfully!

Ooh no, something went wrong!