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 175 — #213<br />
✐<br />
5.3. Amigos (fri<strong>en</strong>ds)<br />
}<br />
x.i = 100; // Direct data manipulation<br />
int main() {<br />
X x;<br />
Z z;<br />
z.g(&x);<br />
} ///:~<br />
struct Y ti<strong>en</strong>e un método f() que modifica un objeto de tipo X. Aquí hay<br />
un poco de lío pues <strong>en</strong> <strong>C++</strong> el compilador necesita que usted declare todo antes<br />
de poder hacer refer<strong>en</strong>cia a ello, así struct Y debe estar declarado antes de que<br />
su método Y::f(X*) pueda ser declarado como fri<strong>en</strong>d <strong>en</strong> struct X. Pero para<br />
declarar Y::f(X*), struct X debe estar declarada antes!<br />
Aquí vemos la solución. Dese cu<strong>en</strong>ta de que Y::f(X*) toma como argum<strong>en</strong>to<br />
la dirección de un objeto de tipo X. Esto es fundam<strong>en</strong>tal pues el compilador siempre<br />
sabe cómo pasar una dirección, que es de un tamaño fijo sin importar el tipo, aunque<br />
no t<strong>en</strong>ga información del tamaño real. Si int<strong>en</strong>ta pasar el objeto completo, el compilador<br />
necesita ver la definición completa de X, para saber el tamaño de lo que quiere<br />
pasar y cómo pasarlo, antes de que le permita declarar una función como Y::g(X).<br />
Pasando la dirección de un X, el compilador le permite hacer una id<strong>en</strong>tificación de<br />
tipo incompleta de X antes de declarar Y::f(X*). Esto se consigue con la declaración:<br />
struct X;<br />
Esta declaración simplem<strong>en</strong>te le dice al compilador que hay una estructura con<br />
ese nombre, así que es correcto referirse a ella siempre que sólo se necesite el nombre.<br />
Ahora, <strong>en</strong> struct X, la función Y::f(X*) puede ser declarada como fri<strong>en</strong>d<br />
sin problemas. Si int<strong>en</strong>ta declararla antes de que el compilador haya visto la especificación<br />
completa de Y, habría dado un error. Esto es una restricción para asegurar<br />
consist<strong>en</strong>cia y eliminar errores.<br />
Fíjese <strong>en</strong> las otras dos funciones fri<strong>en</strong>d. La primera declara una función global<br />
ordinaria g() como fri<strong>en</strong>d. Pero g() no ha sido declarada antes como global!.<br />
Se puede usar fri<strong>en</strong>d de esta forma para declarar la función y darle el estado de<br />
fri<strong>en</strong>d simultáneam<strong>en</strong>te. Esto se exti<strong>en</strong>de a estructuras completas:<br />
fri<strong>en</strong>d struct Z;<br />
es una especificación incompleta del tipo Z, y da a toda la estructura el estado de<br />
fri<strong>en</strong>d.<br />
5.3.1. Amigas anidadas<br />
Hacer una estructura anidada no le da acceso a los miembros privados. Para conseguir<br />
esto, se debe: primero, declarar (sin definir) la estructura anidada, después<br />
declararla como fri<strong>en</strong>d, y finalm<strong>en</strong>te definir la estructura. La definición de la estructura<br />
debe estar separada de su declaración como fri<strong>en</strong>d, si no el compilador la<br />
vería como no miembro. Aquí hay un ejemplo:<br />
175<br />
✐<br />
✐<br />
✐<br />
✐