Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
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 />
✐