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 445 — #483<br />
✐<br />
15.5. Cómo implem<strong>en</strong>ta <strong>C++</strong> la ligadura dinámica<br />
y el objeto se figura que debe hacer con él.<br />
15.5.3. Detrás del telón<br />
Puede ser útil ver el código <strong>en</strong>samblador que se g<strong>en</strong>era con la llamada a una<br />
función virtual, para poder ver como funciona la ligadura dinámica. Aquí está la<br />
salida de un compilador a la llamada<br />
i.adjust(1);<br />
d<strong>en</strong>tro de la función f(Instrum<strong>en</strong>t& i):<br />
push 1<br />
push si<br />
mov bx, word ptr [si]<br />
call word ptr [bx+4]<br />
add sp, 4<br />
Los argum<strong>en</strong>tos de una llamada a una función <strong>C++</strong>, como los de a una función C,<br />
son colocados <strong>en</strong> la pila de derecha a izquierda (este ord<strong>en</strong> es necesario para poder<br />
soportar las listas de argum<strong>en</strong>tos variables de C), por lo que el argum<strong>en</strong>to 1 se pone<br />
al principio <strong>en</strong> la pila. En este punto <strong>en</strong> la función, el registro si (que es parte de<br />
la arquitectura del procesador Intel X86) conti<strong>en</strong>e la dirección de i. También se<br />
introduce <strong>en</strong> la pila porque es la dirección de comi<strong>en</strong>zo del objeto de interés. Hay<br />
que recordar que la dirección del comi<strong>en</strong>zo del objeto corresponde al valor de this,<br />
y this es introducido <strong>en</strong> la pila de manera oculta antes de cualquier llamada<br />
a función, por lo que la función miembro sabe sobre qué objeto <strong>en</strong> concreto está<br />
trabajando. Debido a esto se verá siempre uno más que el número de argum<strong>en</strong>tos<br />
introducidos <strong>en</strong> la pila antes de una llamada a una función miembro (excepto para<br />
las funciones miembro static, que no ti<strong>en</strong><strong>en</strong> this).<br />
Ahora se puede ejecutar la llamada a la función virtual. Primero hay que producir<br />
el VPTR para poder <strong>en</strong>contrar la VTABLE. Para el compilador el VPTR se inserta al<br />
principio del objeto, por lo que el cont<strong>en</strong>ido de this corresponde al VPTR. La línea<br />
mov bx, word ptr [si]<br />
busca la dirección (word) a la que apunta si, que es el VPTR y la coloca d<strong>en</strong>tro<br />
del registro bx.<br />
El VPTR cont<strong>en</strong>ido <strong>en</strong> bx apunta a la dirección inicial de la VTABLE, pero el puntero<br />
de la función a llamar no se <strong>en</strong>cu<strong>en</strong>tra <strong>en</strong> la posición cero de la VTABLE, si no<br />
<strong>en</strong> la segunda posición (debido a que es la tercera función <strong>en</strong> la lista). Debido al modelo<br />
de memoria cada puntero a función ocupa dos bytes, por lo que el compilador<br />
suma cuatro al VPTR para calcular donde está la dirección de la función apropiada.<br />
Hay que hacer notar que este es un valor constante establecido <strong>en</strong> tiempo de compilación,<br />
por lo que lo único que ocurre es que el puntero a función que está <strong>en</strong> la<br />
posición dos apunta a adjust(). Afortunadam<strong>en</strong>te, el compilador se <strong>en</strong>carga de<br />
todo y se asegura de que todos los punteros a funciones <strong>en</strong> todas las VTABLEs de<br />
una jerarquía particular se cre<strong>en</strong> con el mismo ord<strong>en</strong>, a pesar del ord<strong>en</strong> <strong>en</strong> que se<br />
hayan sobreescrito las funciones <strong>en</strong> las clases derivadas.<br />
Una vez se ha calculado <strong>en</strong> la VTABLE la dirección del puntero apropiado, se<br />
llama a la función a la que apunta el puntero. Esto es, se busca la dirección y se llama<br />
445<br />
✐<br />
✐<br />
✐<br />
✐