Tengo problemas para ver la utilidad de los punteros a función. Creo que puede ser útil en algunos casos (que existen, después de todo), pero no puedo pensar en un caso en que es mejor o inevitable el uso de un puntero a función.

Podría dar algún ejemplo de buen uso de punteros a función (en C o C++)?

  • Usted puede encontrar un poco de discusión sobre la función de los punteros en el esta relacionado con LO de la pregunta.
  • posibles duplicados de stackoverflow.com/questions/840501/…
  • De verdad que no. «Cómo se hace un trabajo en TELEVISIÓN?» es una cuestión diferente de la de «¿Qué puedo hacer con una TV?»
  • En C++ es probable que el uso de un functor (en.wikipedia.org/wiki/Function_object#In_C_and_C.2B.2B) en su lugar.
  • En los viejos días oscuros en C++ se «compila» a C, se puede ver cómo los métodos virtuales se implementan – sí, con punteros a función.
  • +1 por el juego de palabras en el título.
  • Muy esencial cuando se quiere usar C++ con un managed C++ o C#, es decir: los delegados y las devoluciones de llamada
  • ¿Cuál es el punto de no punteros de función?

InformationsquelleAutor gramm | 2010-04-07

16 Comentarios

  1. 104

    La mayoría de los ejemplos se reducen a devoluciones de llamada: Se llama a una función f() pasar la dirección de otra función g(), y f() llamadas g() para alguna tarea específica. Si pasa f() la dirección de h() lugar, a continuación, f() volverá a llamar h() lugar.

    Básicamente, esta es una manera de parametrizar una función: a parte de su comportamiento no es rígida en f(), pero en la función de devolución de llamada. Las personas que llaman pueden hacer f() se comportan de manera diferente por el paso de diferentes funciones de devolución de llamada. Un clásico es qsort() de la biblioteca estándar de C que toma su criterio de ordenación como un puntero a una función de comparación.

    En C++, esto se realiza a menudo mediante función de los objetos (también llamado functors). Estos son los objetos que sobrecarga el operador de llamada de función, así que usted puede llamar a ellos como si se tratara de una función. Ejemplo:

    class functor {
      public:
         void operator()(int i) {std::cout << "the answer is: " << i << '\n';}
    };
    
    functor f;
    f(42);

    La idea detrás de esto es que, a diferencia de un puntero a función, una función de objeto puede llevar no sólo a un algoritmo, sino también de datos:

    class functor {
      public:
         functor(const std::string& prompt) : prompt_(prompt) {}
         void operator()(int i) {std::cout << prompt_ << i << '\n';}
      private:
         std::string prompt_;
    };
    
    functor f("the answer is: ");
    f(42);

    Otra ventaja es que a veces es más fácil en línea de las llamadas a los objetos de la función de llamadas a través de punteros a función. Esta es una razón por la clasificación en C++, es a veces más rápido que la clasificación en C.

    • +1 para el ejemplo sólo aquí con real código!
    • +1, ver también esta respuesta para otro ejemplo: stackoverflow.com/questions/1727824/…
    • Usted se olvidó de funciones virtuales, esencialmente, ellos son los punteros a función, así (junto con una estructura de datos que genera el compilador). Además, en C puro puede crear estas estructuras a escribir orientado a objetos de código como se ve en la capa VFS (y en muchos otros lugares) del kernel de Linux.
    • Las funciones virtuales son punteros a función sólo para el compilador de las entidades ejecutoras, y si usted tiene que preguntarse para qué sirven, probablemente (¡ojalá!) raro estar en necesidad de implementar un compilador virtual de la función de mecanismo.
    • Por supuesto tienes razón. Sin embargo, creo que ayuda a entender lo que está pasando en el interior de la abstracción. También, la implementación de su propio vtable en C y escribir orientado a objetos de código no es realmente una buena experiencia de aprendizaje.
    • puntos brownie para proporcionar la respuesta a la vida, el universo y todo lo que junto con lo que se le pidió por OP

  2. 39

    Bien, yo por lo general uso de ellos (profesionalmente) en saltar tablas (ver también esta pregunta de StackOverflow).

    Saltar las mesas son habitualmente (pero no exclusivamente) que se utilizan en máquinas de estado finito para hacer de ellos basados en datos. En lugar de anidado switch/case

      switch (state)
         case A:
           switch (event):
             case e1: ....
             case e2: ....
         case B:
           switch (event):
             case e3: ....
             case e1: ....

    usted puede hacer una matriz 2d o punteros a función y sólo llamar handleEvent[state][event]

  3. 23

    Ejemplos:

    1. De ordenación personalizado/búsquedas
    2. Diferentes
      patrones (como Estrategia, Observador)
    3. Devoluciones de llamada
    • Saltar de mesa es uno de los importantes de la utilización de la misma.
    • Si hay algunos ejemplos de dimensionamiento, este obtendría mi upvote.
    • La estrategia y el observador se están probablemente mejor implementado el uso de funciones virtuales, si C++ está disponible. De otra manera +1.
    • creo que el uso racional de los punteros a función puede hacer observador más compacto y ligero de peso
    • Sólo si rígidamente palo para el GoF definición, con Javaisms fugas a través de. Me gustaría describir la std::sort‘s comp parámetro como una Estrategia de
  4. 10

    El «clásico» ejemplo de la utilidad de los punteros a función es la biblioteca de C de qsort() función, que implementa una Ordenación Rápida. Con el fin de ser universal para cualquier y todas las estructuras de datos que el usuario puede venir para arriba con, tarda un par de punteros void para ordenar los datos y un puntero a una función que sabe cómo comparar dos elementos de estas estructuras de datos. Esto nos permite crear nuestra función de elección para el trabajo, y, de hecho, incluso permite elegir la función de comparación en tiempo de ejecución, por ejemplo, para ordenar de forma ascendente o descendente.

    • No olvides bsearch!
  5. 6

    Voy a ir contra la corriente aquí.

    En C, los punteros a función son la única manera de implementar la personalización, porque no hay ninguna OO.

    En C++, se puede utilizar cualquiera de los punteros de función o functors (objetos de función) para el mismo resultado.

    Los functors tiene un número de ventajas sobre las primas de punteros a función, debido a su objeto de la naturaleza, en particular:

    • Pueden presentar varias sobrecargas de la operator()
    • Que puede tener el estado /la referencia a las variables
    • Que puede ser construida en el lugar (lambda y bind)

    Yo personalmente prefiero functors a los punteros de función (a pesar de que el código repetitivo), principalmente porque la sintaxis para los punteros a función puede conseguir fácilmente peludo (a partir de la Puntero A La Función Tutorial):

    typedef float(*pt2Func)(float, float);
      //defines a symbol pt2Func, pointer to a (float, float) -> float function
    
    typedef int (TMyClass::*pt2Member)(float, char, char);
      //defines a symbol pt2Member, pointer to a (float, char, char) -> int function
      //belonging to the class TMyClass

    La única vez que he visto a los punteros a función se utiliza cuando functors podría no estaba en el Impulso.Espíritu. Tienen absolutamente abusado de la sintaxis para pasar un número arbitrario de parámetros como único parámetro de plantilla.

     typedef SpecialClass<float(float,float)> class_type;

    Pero desde variadic plantillas y expresiones lambda son alrededor de la esquina, no estoy seguro de que vamos a utilizar punteros a función en puro código C++ para largo ahora.

    • Sólo porque usted no ve su punteros a función, no significa que no los uso. Cada vez (a menos que el compilador puede optimizar lejos) llamar a una función virtual, usar el boost bind o function utilizar punteros a función. Es como decir que no se use punteros en C++ debe a que el uso de punteros inteligentes. De todos modos, estoy molesto.
    • Voy a cortésmente de acuerdo. Lo que importa es lo que ver y tipo, que es la sintaxis que se utiliza. No debería importar a usted cómo funciona todo detrás de las escenas: esto es lo que la abstracción se acerca.
  6. 5

    En C, el uso clásico es el la función qsort, donde el cuarto parámetro es un puntero a una función que va a utilizar para realizar el pedido dentro de la especie. En C++, uno tendería a utilizar functors (objetos que se parecen a las funciones) para este tipo de cosas.

    • No olvides bsearch!
    • la lista es interminable.
    • Yo estaba señalando el único otro ejemplo de esto en la biblioteca estándar de C. Los ejemplos que citas son parte de las bibliotecas de terceros.
  7. 5

    De acuerdo con todo lo anterior, además de….
    Cuando se carga una dll de forma dinámica en tiempo de ejecución tendrá punteros de función para llamar a las funciones.

    • Hago esto todo el tiempo para el soporte de Windows XP y todavía usan Windows 7 golosinas. +1.
  8. 5

    He utilizado los punteros a función recientemente para crear una capa de abstracción.

    Tengo un programa escrito en C puro que se ejecuta en sistemas embebidos. Es compatible con múltiples variantes de hardware. Dependiendo del hardware que estoy ejecutando, se debe llamar a diferentes versiones de algunas funciones.

    En el momento de la inicialización, el programa de las cifras de lo que el hardware que se está ejecutando y rellena los punteros a función. Todos los de nivel superior rutinas en el programa acaba de llamar a las funciones que hace referencia a los punteros. Puedo añadir soporte para nuevo hardware variantes sin tocar el más alto nivel de las rutinas.

    Solía usar switch/case declaraciones para seleccionar la función adecuada de las versiones, pero esto se convirtió en práctica como el programa se hizo para apoyar a más y más hardware variantes. He tenido que añadir el caso de las declaraciones de todo el lugar.

    También probé intermedio de la función de las capas que averiguar la función a utilizar, pero no ayudan mucho. Yo todavía tenía que actualizar caso de declaraciones en varios lugares siempre hemos añadido una nueva variante. Con los punteros de función, sólo tengo que cambiar la función de inicialización.

  9. 3

    Como Rica dijo anteriormente, es muy habitual para las funciones punteros en Windows para hacer referencia a una dirección que almacena la función.

    Cuando la programación en C language en la plataforma de Windows, básicamente, de cargar un archivo DLL en memoria principal(utilizando LoadLibrary) y utilizar las funciones que se almacenan en DLL que usted necesita para crear funciones y punteros apuntan a estas direcciones (utilizando GetProcAddress).

    Referencias:

  10. 2

    Función se pueden utilizar punteros en C para crear una interfaz con la cual el programa. Dependiendo de la funcionalidad específica que se necesita en tiempo de ejecución, una implementación diferente puede ser asignado a la función de puntero.

  11. 2

    Mi uso principal de ellos ha sido devoluciones de llamada: cuando usted necesita para guardar información acerca de una función a llamar más tarde.

    Decir que estás escribiendo Bomberman. 5 segundos después de que la persona cae la bomba, se debe explotar (llame a la explode() función).

    Ahora hay 2 maneras de hacerlo. Una forma de hacerlo es «sondeo» todas las bombas en la pantalla para ver si están listos para explotar en el bucle principal.

    foreach bomb in game 
       if bomb.boomtime()
           bomb.explode()

    Otra forma es colocar una devolución de llamada a su sistema de reloj. Cuando la bomba esté colocada, usted añade una devolución de llamada para hacer la llamada bomba.explode() cuando el tiempo es correcto.

    //user placed a bomb
    Bomb* bomb = new Bomb()
    make callback( function=bomb.explode, time=5 seconds ) ;
    
    //IN the main loop:
    foreach callback in callbacks
        if callback.timeToRun
             callback.function()

    Aquí callback.function() puede ser cualquier función, porque es un puntero a función.

  12. 2

    Una perspectiva diferente, además de otras buenas respuestas aquí:

    En C, hay sólo punteros a función, no hay funciones.

    Quiero decir, que las funciones de escritura, pero que no puede manipular funciones. No hay tiempo de ejecución de representación de una función como tal. Ni siquiera se puede llamar una «función». Cuando usted escribe:

    my_function(my_arg);

    lo que en realidad estamos diciendo es «realizar una llamada a la my_function puntero con el argumento especificado». Usted está haciendo una llamada a través de un puntero a función. Este la desintegración de la función de puntero significa que los siguientes comandos son equivalentes a la anterior llamada a la función:

    (&my_function)(my_arg);
    (*my_function)(my_arg);
    (**my_function)(my_arg);
    (&**my_function)(my_arg);
    (***my_function)(my_arg);

    y así sucesivamente (gracias @LuuVinhPhuc).

    Así que, ya estás utilizando punteros de función como valores. Obviamente, usted quiere tener variables de esos valores – y aquí es donde todos los otros usos metion vienen en: Polimorfismo/personalización (como en qsort), las devoluciones de llamada, saltar, etc mesas.

    En C++, las cosas son un poco más complicadas, ya que hemos de lambdas, y los objetos con operator(), e incluso un std::function clase, pero el principio sigue siendo básicamente el mismo.

  13. 1

    Para OO de idiomas, para realizar llamadas polimórficas detrás de las escenas (esto también es válido para C hasta cierto punto, supongo).

    Por otra parte, son muy útiles para inyectar un comportamiento diferente a otra función (foo) en tiempo de ejecución. Que hace la función foo función de orden superior. Además de su flexibilidad, lo que hace que los foo código más legible, ya que vamos a sacar ese extra de la lógica de «if-else» de ella.

    Que permite a muchas otras cosas útiles en Python como los generadores, cierres, etc.

  14. 1

    Uso de la función de puntero

    A la función de llamada de forma dinámica según la entrada del usuario.
    Mediante la creación de un mapa de cadena y la función de puntero en este caso.

    #include<iostream>
    #include<map>
    using namespace std;
    //typedef  map<string, int (*)(int x, int y) > funMap;
    #define funMap map<string, int (*)(int, int)>
    funMap objFunMap;
    
    int Add(int x, int y)
    {
        return x+y;
    }
    int Sub(int x, int y)
    {
            return x-y;
    }
    int Multi(int x, int y)
    {
            return x*y;
    }
    void initializeFunc()
    {
            objFunMap["Add"]=Add;
            objFunMap["Sub"]=Sub;
            objFunMap["Multi"]=Multi;
    }
    int main()
    {
        initializeFunc();
    
        while(1)
        {
            string func;
            cout<<"Enter your choice( 1. Add 2. Sub 3. Multi) : ";
            int no, a, b;
            cin>>no;
    
            if(no==1)
                func = "Add";
            else if(no==2)
                func = "Sub";
            else if(no==3)
                func = "Multi";
            else 
                break;
    
            cout<<"\nEnter 2 no :";
                    cin>>a>>b;
    
            //function is called using function pointer based on user input
            //If user input is 2, and a=10, b=3 then below line will expand as "objFuncMap["Sub"](10, 3)"
            int ret = objFunMap[func](a, b);      
            cout<<ret<<endl;
        }
        return 0;
    }

    De esta manera hemos utilizado la función de puntero real en nuestra sociedad.
    Usted puede escribir ‘n’ número de la función y la llamada utilizando este método.

    De SALIDA:

     Introduzca su elección( 1. Agregar 2. Sub 3. Multi) : 1 
    Introduzca 2 no :2 4 
    6 
    Introduzca su elección( 1. Agregar 2. Sub 3. Multi) : 2 
    Introduzca 2 no : 10 3 
    7 
    Introduzca su elección( 1. Agregar 2. Sub 3. Multi) : 3 
    Introduzca 2 no : 3 6 
    18 
    
  15. 0

    Puedo usar punteros a función ampliamente, para la simulación de microprocesadores que tienen de 1 byte códigos de operación. Una matriz de 256 punteros a función es la manera natural para implementar esto.

  16. 0

    Un uso de la función de puntero podría ser donde podemos no quiere modificar el código donde la función es recibir llamadas (refiriéndose a la llamada puede ser condicional y bajo condiciones diferentes, tenemos que hacer otro tipo de tratamiento).
    Aquí los punteros de función muy útil, ya que no tenemos necesidad de modificar el código en el lugar donde la función es recibir llamadas. Simplemente llamamos a la función utilizando el puntero de la función con los argumentos adecuados.
    La función de puntero puede apuntar a diferentes funciones de forma condicional. (Esto se puede hacer en algún momento durante la fase de inicialización). Por otra parte el modelo anterior es muy útil, si no estamos en posición para modificar el código donde está recibiendo la llamada (supongamos que es un API de biblioteca que no podemos modificar). La API utiliza un puntero a función para llamar a la adecuada función definida por el usuario.

Dejar respuesta

Please enter your comment!
Please enter your name here