2010-11-28 14 views
341

Estoy aprendiendo cómo cargar dinámicamente DLL pero lo que no entiendo es esta líneapuntero de la función Typedef?

typedef void (*FunctionFunc)(); 

Tengo un par de preguntas. Si alguien puede responderlas, estaría agradecido.

  1. ¿Por qué se usa typedef?
  2. La sintaxis parece extraña; después de void ¿no debería haber un nombre de función o algo así? Parece una función anónima.
  3. ¿Se ha creado un puntero a función para almacenar la dirección de memoria de una función?

Así que estoy confundido por el momento; ¿Puedes aclararme las cosas?

+4

Echa un vistazo al enlace (última sección) http://www.learncpp.com/cpp-tutorial/78-function-pointers/ – enthusiasticgeek

+5

Debe tenerse en cuenta que, dado que C++ 11 'usando FunctionFunc = void (*)(); 'se puede usar en su lugar. Es un poco más claro que solo está declarando un nombre para un tipo (puntero a función) – user362515

+0

solo para agregar a @ user362515, una forma un poco más clara para mí es: 'using FunctionFunc = void (void);' – topspin

Respuesta

356

typedef es una construcción de lenguaje que asocia un nombre a un tipo.
que lo utilice la misma manera que utilizaría el tipo original, por ejemplo

typedef int myinteger; 
    typedef char *mystring; 
    typedef void (*myfunc)(); 

usarlos como

myinteger i; // is equivalent to int i; 
    mystring s; // is the same as  char *s; 
    myfunc f;  // compile equally as void (*f)(); 

Como se puede ver, sólo podría reemplazar el typedefed nombre con su definición dada arriba.

La dificultad radica en el puntero a la sintaxis de funciones y la legibilidad en C y C++, y el typedef puede mejorar la legibilidad de tales declaraciones. Sin embargo, la sintaxis es apropiada, ya que las funciones -a diferencia de otros tipos más simples- pueden tener un valor de retorno y parámetros, por lo tanto, la declaración a veces larga y compleja de un puntero a la función.

La legibilidad puede comenzar a ser realmente complicada con los punteros a los arreglos de funciones, y algunos otros sabores aún más indirectos.

para responder a sus tres preguntas

  • ¿Por qué se utiliza typedef? Para facilitar la lectura del código, especialmente para los punteros a funciones o nombres de estructura.

  • La sintaxis es impar (en el puntero a funcionar declaración) que la sintaxis no es evidente para leer, al menos al comenzar. Usar una declaración typedef en su lugar facilita la lectura

  • ¿Se ha creado un puntero a función para almacenar la dirección de memoria de una función? Sí, un puntero de función almacena la dirección de una función. Esto no tiene nada que ver con la construcción typedef que solo facilita la escritura/lectura de un programa; el compilador simplemente expande la definición de typedef antes de compilar el código real.

Ejemplo:

typedef int (*t_somefunc)(int,int); 

int product(int u, int v) { 
    return u*v; 
} 

t_somefunc afunc = &product; 
... 
int x2 = (*afunc)(123, 456); // call product() to calculate 123*456 
+5

en el último ejemplo, no solo 'cuadrado' se referiría a lo mismo, es decir, un puntero a la función en lugar de usar & square. – pranavk

+2

Pregunta, en el primer ejemplo de typedef que tiene de la forma 'typedef type alias' pero con punteros a funciones alli solo parece haber 2 argumentos,' typedef type'. ¿Alias ​​está predeterminado al nombre especificado en el argumento de tipo? – dchhetri

+1

@pranavk: Sí, 'square' y' & square' (y, de hecho, '* square' y' ** square') se refieren al mismo puntero de función. –

147
  1. typedef se utiliza para alias tipos; en este caso, aliasing FunctionFunc a void(*)().

  2. De hecho, la sintaxis tiene un aspecto extraño, echar un vistazo a esto:

    typedef void  (*FunctionFunc) (); 
    //  ^   ^  ^
    //  return type  type name arguments 
    
  3. No, esto simplemente declara que el tipo FunctionFunc será un puntero de función, que no definen uno, de esta manera:

    FunctionFunc x; 
    void doSomething() { printf("Hello there\n"); } 
    x = &doSomething; 
    
    x(); //prints "Hello there" 
    
+20

'typedef' does * not * declara un nuevo tipo. puede tener muchos nombres 'typedef' definidos del mismo tipo, y son * not * distinct (por ejemplo, sobrecarga de funciones). hay algunas circunstancias en las que, con respecto a cómo puede usar el nombre, un nombre 'typedef'-defined no es exactamente equivalente a lo que se define como, pero múltiples nombres' typedef'-defined para el mismo, son equivalentes. –

+0

Ah, lo entiendo ahora. Gracias. –

+0

@Jack, ¡De nada! :) –

24

Sin la palabra typedef, en C++ la declaración sería DECLA re una variable FunctionFunc de tipo puntero a función de sin argumentos, que devuelve void.

Con el typedef, en su lugar se define FunctionFunc como un nombre para ese tipo.

+4

Esta es una muy buena manera de pensar sobre eso. Si lee las otras respuestas detenidamente, en realidad no abordan la confusión del PO sobre el enredo del alias y el nombre. Aprendí algo nuevo leyendo esta publicación. –

0
#include <stdio.h> 
#include <math.h> 

/* 
To define a new type name with typedef, follow these steps: 
1. Write the statement as if a variable of the desired type were being declared. 
2. Where the name of the declared variable would normally appear, substitute the new type name. 
3. In front of everything, place the keyword typedef. 
*/ 

// typedef a primitive data type 
typedef double distance; 

// typedef struct 
typedef struct{ 
    int x; 
    int y; 
} point; 

//typedef an array 
typedef point points[100]; 

points ps = {0}; // ps is an array of 100 point 

// typedef a function 
typedef distance (*distanceFun_p)(point,point) ; // TYPE_DEF distanceFun_p TO BE int (*distanceFun_p)(point,point) 

// prototype a function  
distance findDistance(point, point); 

int main(int argc, char const *argv[]) 
{ 
    // delcare a function pointer 
    distanceFun_p func_p; 

    // initialize the function pointer with a function address 
    func_p = findDistance; 

    // initialize two point variables 
    point p1 = {0,0} , p2 = {1,1}; 

    // call the function through the pointer 
    distance d = func_p(p1,p2); 

    printf("the distance is %f\n", d); 

    return 0; 
} 

distance findDistance(point p1, point p2) 
{ 
distance xdiff = p1.x - p2.x; 
distance ydiff = p1.y - p2.y; 

return sqrt((xdiff * xdiff) + (ydiff * ydiff)); 
} 
+1

¿En qué circunstancias se necesita el '&'? Por ejemplo, ¿funcionan igual de bien func_p = & findDistance y func_p = findDistance? – Donna

+1

Un nombre de función es un puntero, por lo que no necesita usar '&' con él. En otras palabras, '&' es opcional cuando se consideran los punteros a funciones. Sin embargo, para el tipo de datos primitivo necesita usar '&' para obtener su dirección. – Amjad

+1

Siempre me ha parecido raro que el '&' pueda ser opcional. Si un typedef se usa para crear un puntero a un primitivo (es decir, 'typedef (* double) p', ¿el '&' opcional? – Donna

3

Si puede utilizar C++ 11 es posible que desee utilizar std::function y using palabra clave.

using FunctionFunc = std::function<void(int arg1, std::string arg2)>; 
Cuestiones relacionadas