Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO Pensar en C++ (Volumen 1) - Grupo ARCO

arco.esi.uclm.es
from arco.esi.uclm.es More from this publisher
13.01.2015 Views

✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 128 — #166 ✐ Capítulo 3. C en C++ Para repasar, «empezar en el medio» («funcPtr es un ...», va a la derecha (nada aquí - pare en el paréntesis derecho), va a la izquierda y encuentra el * («... puntero a ...»), va a la derecha y encuentra la lista de argumentos vacía («... función que no tiene argumentos ...») va a la izquierda y encuentra el void («funcPtr es un puntero a una función que no tiene argumentos y retorna void»). Quizá se pregunte porqué *funcPtr necesita paréntesis. Si no los usara, el compilador podría ver: void *funcPtr(); Lo que corresponde a la declaración de una función (que retorna un void*) en lugar de definir una variable. Se podría pensar que el compilador sería capaz distinguir una declaración de una definición por lo que se supone que es. El compilador necesita los paréntesis para «tener contra qué chocar» cuando vaya hacia la izquierda y encuentre el *, en lugar de continuar hacia la derecha y encontrar la lista de argumentos vacía. 3.10.2. Declaraciones y definiciones complicadas Al margen, una vez que entienda cómo funciona la sintáxis de declaración de C y C++ podrá crear elementos más complicados. Por ejemplo: //: V1C03:ComplicatedDefinitions.cpp /* 1. */ void * (*(*fp1)(int))[10]; /* 2. */ float (*(*fp2)(int,int,float))(int); /* 3. */ typedef double (*(*(*fp3)())[10])(); fp3 a; /* 4. */ int (*(*f4())[10])(); int main() {} Estudie cada uno y use la regla derecha-izquierda para entenderlos. El número 1 dice «fp1 es un puntero a una función que toma un entero como argumento y retorna un puntero a un array de 10 punteros void». El 2 dice «fp2 es un puntero a función que toma tres argumentos (int, int y float) de retorna un puntero a una función que toma un entero como argumento y retorna un float» Si necesita crear muchas definiciones complicadas, debería usar typedef. El número 3 muestra cómo un typedef ahorra tener que escribir una descripción complicada cada vez. Dice «Un fp3 es un puntero a una función que no tiene argumentos y que retorna un puntero a un array de 10 punteros a funciones que no tienen argumentos y retornan doubles». Después dice «a es una variable de ese tipo fp3». typedef es útil para construir descripciones complicadas a partir de otras simples. El 4 es una declaración de función en lugar de una definición de variable. Dice «f4 es una función que retorna un puntero a un array de 10 punteros a funciones que retornan enteros». 128 ✐ ✐ ✐ ✐

✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 129 — #167 ✐ 3.10. Direcciones de función Es poco habitual necesitar declaraciones y definiciones tan complicadas como éstas. Sin embargo, si se propone entenderlas, no le desconcertarán otras algo menos complicadas pero que si encontrará en la vida real. 3.10.3. Uso de un puntero a función Una vez que se ha definido un puntero a función, debe asignarle la dirección de una función antes de poder usarlo. Del mismo modo que la dirección de un array arr[10] se obtiene con el nombre del array sin corchetes (arr), la dirección de una función func() se obtiene con el nombre de la función sin lista de argumentos (func). También puede usar una sintáxis más explícita: &func(). Para invocar la función, debe dereferenciar el puntero de la misma forma que lo ha declarado (recuerde que C y C++ siempre intentan hacer que las definiciones se parezcan al modo en que se usan). El siguiente ejemplo muestra cómo se define y usa un puntero a función: //: C03:PointerToFunction.cpp // Defining and using a pointer to a function #include using namespace std; void func() { cout

✐<br />

✐<br />

✐<br />

“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 128 — #166<br />

✐<br />

Capítulo 3. C <strong>en</strong> <strong>C++</strong><br />

Para repasar, «empezar <strong>en</strong> el medio» («funcPtr es un ...», va a la derecha (nada<br />

aquí - pare <strong>en</strong> el paréntesis derecho), va a la izquierda y <strong>en</strong>cu<strong>en</strong>tra el * («... puntero<br />

a ...»), va a la derecha y <strong>en</strong>cu<strong>en</strong>tra la lista de argum<strong>en</strong>tos vacía («... función que no<br />

ti<strong>en</strong>e argum<strong>en</strong>tos ...») va a la izquierda y <strong>en</strong>cu<strong>en</strong>tra el void («funcPtr es un puntero<br />

a una función que no ti<strong>en</strong>e argum<strong>en</strong>tos y retorna void»).<br />

Quizá se pregunte porqué *funcPtr necesita paréntesis. Si no los usara, el compilador<br />

podría ver:<br />

void *funcPtr();<br />

Lo que corresponde a la declaración de una función (que retorna un void*) <strong>en</strong><br />

lugar de definir una variable. Se podría p<strong>en</strong>sar que el compilador sería capaz distinguir<br />

una declaración de una definición por lo que se supone que es. El compilador<br />

necesita los paréntesis para «t<strong>en</strong>er contra qué chocar» cuando vaya hacia la izquierda<br />

y <strong>en</strong>cu<strong>en</strong>tre el *, <strong>en</strong> lugar de continuar hacia la derecha y <strong>en</strong>contrar la lista de<br />

argum<strong>en</strong>tos vacía.<br />

3.10.2. Declaraciones y definiciones complicadas<br />

Al marg<strong>en</strong>, una vez que <strong>en</strong>ti<strong>en</strong>da cómo funciona la sintáxis de declaración de C<br />

y <strong>C++</strong> podrá crear elem<strong>en</strong>tos más complicados. Por ejemplo:<br />

//: V1C03:ComplicatedDefinitions.cpp<br />

/* 1. */ void * (*(*fp1)(int))[10];<br />

/* 2. */ float (*(*fp2)(int,int,float))(int);<br />

/* 3. */ typedef double (*(*(*fp3)())[10])();<br />

fp3 a;<br />

/* 4. */ int (*(*f4())[10])();<br />

int main() {}<br />

Estudie cada uno y use la regla derecha-izquierda para <strong>en</strong>t<strong>en</strong>derlos. El número<br />

1 dice «fp1 es un puntero a una función que toma un <strong>en</strong>tero como argum<strong>en</strong>to y<br />

retorna un puntero a un array de 10 punteros void».<br />

El 2 dice «fp2 es un puntero a función que toma tres argum<strong>en</strong>tos (int, int y float)<br />

de retorna un puntero a una función que toma un <strong>en</strong>tero como argum<strong>en</strong>to y retorna<br />

un float»<br />

Si necesita crear muchas definiciones complicadas, debería usar typedef. El número<br />

3 muestra cómo un typedef ahorra t<strong>en</strong>er que escribir una descripción complicada<br />

cada vez. Dice «Un fp3 es un puntero a una función que no ti<strong>en</strong>e argum<strong>en</strong>tos<br />

y que retorna un puntero a un array de 10 punteros a funciones que no ti<strong>en</strong><strong>en</strong> argum<strong>en</strong>tos<br />

y retornan doubles». Después dice «a es una variable de ese tipo fp3».<br />

typedef es útil para construir descripciones complicadas a partir de otras simples.<br />

El 4 es una declaración de función <strong>en</strong> lugar de una definición de variable. Dice<br />

«f4 es una función que retorna un puntero a un array de 10 punteros a funciones<br />

que retornan <strong>en</strong>teros».<br />

128<br />

✐<br />

✐<br />

✐<br />

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

Saved successfully!

Ooh no, something went wrong!