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 406 — #444<br />
✐<br />
Capítulo 14. Her<strong>en</strong>cia y Composición<br />
si se hubiese creado un objeto X d<strong>en</strong>tro de la clase Y <strong>en</strong> vez de heredar de X. Tanto<br />
los miembros objetos y la clase base son conocidos como subobjetos.<br />
Todos los elem<strong>en</strong>tos privados de X continúan si<strong>en</strong>do privados <strong>en</strong> Y; esto es, aunque<br />
Y hereda de X no significa que Y pueda romper el mecanismo de protección. Los<br />
elem<strong>en</strong>tos privados de X continúan existi<strong>en</strong>do, ocupando su espacio - sólo que no se<br />
puede acceder a ellos directam<strong>en</strong>te.<br />
En main() observamos que los datos de Y están combinados con los datos de X<br />
porque sizeof(Y) es el doble de grande que el sizeof(X).<br />
Observará que la clase base es precedida por public. Durante la her<strong>en</strong>cia, por defecto,<br />
todo es privado. Si la clase base no estuviese precedida por public, significaría<br />
que todos los miembros públicos de la clase base serían privados <strong>en</strong> la clase derivada.<br />
Esto, <strong>en</strong> la mayoría de ocasiones no es lo deseado [51]; el resultado que se desea<br />
es mant<strong>en</strong>er todos los miembros públicos de la clase base <strong>en</strong> la clase derivada. Para<br />
hacer esto, se usa la palabra clave public durante la her<strong>en</strong>cia.<br />
En change(), se utiliza a la función de la clase base permute(). La clase derivada<br />
ti<strong>en</strong>e acceso directo a todas las funciones públicas de la clase base.<br />
La función set() <strong>en</strong> la clase derivada redefine la función set() de la clase base. Esto<br />
es, si llama a las funciones read() y permute() de un objeto Y, conseguirá las versiones<br />
de la clase base (esto es lo que esta ocurri<strong>en</strong>do d<strong>en</strong>tro de main()). Pero si llamamos<br />
a set() <strong>en</strong> un objeto Y, conseguiremos la versión redefinida. Esto significa que si no<br />
deseamos un comportami<strong>en</strong>to de una función durante la her<strong>en</strong>cia, se puede cambiar.<br />
(También se pued<strong>en</strong> añadir funciones completam<strong>en</strong>te nuevas como change().)<br />
Sin embargo, cuando redefinimos una función, puede ser que desee llamar a la<br />
versión de la clase base. Si, d<strong>en</strong>tro de set(), simplem<strong>en</strong>te llama a set(), conseguiremos<br />
una versión local de la función - una función recursiva. Para llamar a la versión de<br />
la clase base, se debe explícitam<strong>en</strong>te utilizar el nombre de la clase base y el operador<br />
de resolución de alcance.<br />
14.3. Lista de inicializadores de un constructor<br />
Hemos visto lo importante que es <strong>en</strong> <strong>C++</strong> garantizar una correcta inicialización,<br />
y esto no va a cambiar <strong>en</strong> la composición ni <strong>en</strong> la her<strong>en</strong>cia. Cuando se crea un objeto,<br />
el compilador garantiza la ejecución todos los constructores para cada uno de los<br />
subobjetos. Hasta ahora, <strong>en</strong> los ejemplos, todos los subobjetos ti<strong>en</strong><strong>en</strong> un constructor<br />
por defecto, que es ejecutado por el compilador automáticam<strong>en</strong>te. Pero que ocurre si<br />
uno de nuestros subobjetos no ti<strong>en</strong>e constructores por defecto, o si queremos cambiar<br />
los parámetros por defecto de un constructor. Esto supone un problema, porque el<br />
constructor de la nueva clase no ti<strong>en</strong>e permiso para acceder a los miembros privados<br />
del subobjeto y por ello, no puede inicializarlos directam<strong>en</strong>te.<br />
La solución es simple: ejecutar el constructor del subobjeto. <strong>C++</strong> proporciona una<br />
sintaxis especial para ello, la lista de inicializadores de un constructor. La forma de<br />
la lista de inicializadores de un constructor demuestra como actúa como la her<strong>en</strong>cia.<br />
Con la her<strong>en</strong>cia, las clases bases son colocadas después de dos puntos y justo<br />
después, puede abrir la llave para empezar con el cuerpo de la clase. En la lista de<br />
inicializadores de un constructor, se coloca las llamadas a los constructores de los<br />
subobjetos, después los argum<strong>en</strong>tos del constructor y los dos puntos, pero todo esto,<br />
antes de abrir el brazo del cuerpo de la función. En una clase MyType, que hereda<br />
de Bar, sería de la sigui<strong>en</strong>te manera:<br />
406<br />
✐<br />
✐<br />
✐<br />
✐