Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO Pensar en C++ (Volumen 1) - Grupo ARCO
✐ ✐ ✐ “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
- Page 115 and 116: ✐ ✐ ✐ “Volumen1” — 2012
- Page 117 and 118: ✐ ✐ ✐ “Volumen1” — 2012
- Page 119 and 120: ✐ ✐ ✐ “Volumen1” — 2012
- Page 121 and 122: ✐ ✐ ✐ “Volumen1” — 2012
- Page 123 and 124: ✐ ✐ ✐ “Volumen1” — 2012
- Page 125 and 126: ✐ ✐ ✐ “Volumen1” — 2012
- Page 127 and 128: ✐ ✐ ✐ “Volumen1” — 2012
- Page 129 and 130: ✐ ✐ ✐ “Volumen1” — 2012
- Page 131 and 132: ✐ ✐ ✐ “Volumen1” — 2012
- Page 133 and 134: ✐ ✐ ✐ “Volumen1” — 2012
- Page 135 and 136: ✐ ✐ ✐ “Volumen1” — 2012
- Page 137 and 138: ✐ ✐ ✐ “Volumen1” — 2012
- Page 139 and 140: ✐ ✐ ✐ “Volumen1” — 2012
- Page 141 and 142: ✐ ✐ ✐ “Volumen1” — 2012
- Page 143 and 144: ✐ ✐ ✐ “Volumen1” — 2012
- Page 145 and 146: ✐ ✐ ✐ “Volumen1” — 2012
- Page 147 and 148: ✐ ✐ ✐ “Volumen1” — 2012
- Page 149 and 150: ✐ ✐ ✐ “Volumen1” — 2012
- Page 151 and 152: ✐ ✐ ✐ “Volumen1” — 2012
- Page 153 and 154: ✐ ✐ ✐ “Volumen1” — 2012
- Page 155 and 156: ✐ ✐ ✐ “Volumen1” — 2012
- Page 157 and 158: ✐ ✐ ✐ “Volumen1” — 2012
- Page 159 and 160: ✐ ✐ ✐ “Volumen1” — 2012
- Page 161 and 162: ✐ ✐ ✐ “Volumen1” — 2012
- Page 163 and 164: ✐ ✐ ✐ “Volumen1” — 2012
- Page 165: ✐ ✐ ✐ “Volumen1” — 2012
- Page 169 and 170: ✐ ✐ ✐ “Volumen1” — 2012
- Page 171 and 172: ✐ ✐ ✐ “Volumen1” — 2012
- Page 173 and 174: ✐ ✐ ✐ “Volumen1” — 2012
- Page 175 and 176: ✐ ✐ ✐ “Volumen1” — 2012
- Page 177 and 178: ✐ ✐ ✐ “Volumen1” — 2012
- Page 179 and 180: ✐ ✐ ✐ “Volumen1” — 2012
- Page 181 and 182: ✐ ✐ ✐ “Volumen1” — 2012
- Page 183 and 184: ✐ ✐ ✐ “Volumen1” — 2012
- Page 185 and 186: ✐ ✐ ✐ “Volumen1” — 2012
- Page 187 and 188: ✐ ✐ ✐ “Volumen1” — 2012
- Page 189 and 190: ✐ ✐ ✐ “Volumen1” — 2012
- Page 191 and 192: ✐ ✐ ✐ “Volumen1” — 2012
- Page 193 and 194: ✐ ✐ ✐ “Volumen1” — 2012
- Page 195 and 196: ✐ ✐ ✐ “Volumen1” — 2012
- Page 197 and 198: ✐ ✐ ✐ “Volumen1” — 2012
- Page 199 and 200: ✐ ✐ ✐ “Volumen1” — 2012
- Page 201 and 202: ✐ ✐ ✐ “Volumen1” — 2012
- Page 203 and 204: ✐ ✐ ✐ “Volumen1” — 2012
- Page 205 and 206: ✐ ✐ ✐ “Volumen1” — 2012
- Page 207 and 208: ✐ ✐ ✐ “Volumen1” — 2012
- Page 209 and 210: ✐ ✐ ✐ “Volumen1” — 2012
- Page 211 and 212: ✐ ✐ ✐ “Volumen1” — 2012
- Page 213 and 214: ✐ ✐ ✐ “Volumen1” — 2012
- Page 215 and 216: ✐ ✐ ✐ “Volumen1” — 2012
✐<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 />
✐