2008-12-05 8 views
26

que estoy haciendo algo como esto:¿Es posible usar la señal dentro de una clase de C++?

#include <signal.h> 

class myClass { 

    public: 

    void myFunction() 
    { 
    signal(SIGIO,myHandler); 
    } 

    void myHandler (int signum) 
    { 
    /** 
    * Handling code 
    */ 
    } 

    } 

estoy trabajando en Ubuntu, usando gcc.

Pero no compilará. Se queja con:

error: the argument with type void (MyClass::)(int) doesn't agree with void (*) (int)

¿Alguna pista? ¿O tal vez es solo que no puedo usar una señal dentro de las clases? ¿Las señales solo están permitidas en C?

El mensaje de error es una traducción aproximada porque mi compilador no está en inglés.

+0

Mira que las señales no están protegidas por hebras, por lo que es posible que no desee volver a examinar esto si necesarry –

+0

La razón es necesario utilizar un método estático (como se describe más adelante), es que llamar a un método que necesita una instancia de la clase (un objeto). No hay forma de pasar un objeto para señalizar, por lo que debe ser un puntero de función normal (no un puntero de método). –

+0

@Robert Gould: cierto; pero no realmente relevante para el tema. –

Respuesta

35

El segundo parámetro de la señal debe ser un puntero a una función que acepte un vacío int y de retorno. Lo que está pasando para señalizar es un puntero a una función miembro que acepta un vacío int y return (su tipo es void (myClass::*)(int)). Veo tres posibilidades para superar este problema:

1 - Su método myHandler puede ser estática: esto es muy bueno, que sea estática

class myClass 
{ 
    public: 
    void myFunction() 
    { 
     signal(SIGIO, myClass::myHandler); 
    } 

    static void myHandler (int signum) 
    { 
     // handling code 
    } 
}; 

2 - Su método no debe ser estática: si' Si planeas utilizar la señal con una sola instancia, puedes crear un objeto estático privado y escribir un método estático que simplemente llame al método en este objeto. Algo a lo largo de las líneas de

class myClass 
{ 
    public: 
    void myFunction() 
    { 
     signal(SIGIO, myClass::static_myHandler); 
    } 

    void myHandler (int signum) 
    { 
     // handling code 
    } 

    static void static_myHandler(int signum) 
    { 
     instance.myHandler(signum); 
    } 

    private: 
    static myClass instance; 
}; 

3 - Sin embargo, si usted está planeando sobre el uso de la señal con varias instancias, las cosas se pondrán más complicado. Tal vez una solución sería la de almacenar cada instancia que desea manipular en un vector estático, e invocando el método en cada uno de los siguientes:

class myClass 
{ 
    public: 
    void myFunction() // registers a handler 
    { 
     instances.push_back(this); 
    } 

    void myHandler (int signum) 
    { 
     // handling code 
    } 

    static void callHandlers (int signum) // calls the handlers 
    { 
     std::for_each(instances.begin(), 
         instances.end(), 
         std::bind2nd(std::mem_fun(&myClass::myHandler), signum)); 
    } 
    private: 
    static std::vector<myClass *> instances; 
}; 

y en algún lugar, hacer una sola llamada a

signal(SIGIO, myClass::callHandlers); 

Pero Creo que si terminas usando la última solución, probablemente deberías pensar en cambiar tu diseño de manejo :-)!

+0

Su segundo ejemplo no es C++ estándar. – dalle

+0

¿Eso es porque olvidé la palabra clave estática? Si es así, ¡está corregido! –

+0

este es el error que estoy obteniendo cuando seguí el segundo método 'error: 'instancia' no se declaró en este ámbito' – molecule

9

pasar un puntero a un método, que debe ser un método estático y debe especificar el nombre de la clase.

Prueba esto:

class myClass { 
    void myFunction() 
    { 
    signal(SIGIO, myClass::myHandler); 
    } 

    static void myHandler (int signum) 
    { 
    // blabla 
    } 
}; 

Y también debe leer el enlace suministrado por Baget, la paragraph 33.2 in the C++ FAQ.

+0

¡simple y exacto! – parasrish

1

En realidad, los manejadores de señal C++ no tienen permitido utilizar ninguna instalación que no esté presente tanto en C como en C++ (excepto que en C++ 11 pueden usar átomos), y se requiere el uso del enlace C. Citando C++11 draft n3242 sección 18.10   "Otro soporte de ejecución" [support.runtime] (párrafo 8),

The common subset of the C and C++ languages consists of all declarations, definitions, and expressions that may appear in a well formed C++ program and also in a conforming C program. A POF (“plain old function”) is a function that uses only features from this common subset, and that does not directly or indirectly use any function that is not a POF, except that it may use functions defined in Clause 29 that are not member functions. All signal handlers shall have C linkage. A POF that could be used as a signal handler in a conforming C program does not produce undefined behavior when used as a signal handler in a C++ program. The behavior of any other function used as a signal handler in a C++ program is implementation-defined.

(Cláusula 29 siendo el uno en atómica.)

1
#include <signal.h> 

class myClass { 

private: 
    static myClass* me; 

public: 
    myClass(){ me=this; } 

    void myFunction(){ 
    signal(SIGIO,myClass::myHandler); 
    } 

    void my_method(){ } 

    static void myHandler (int signum){ 
    me->my_method(); 
} 
} 
+0

Si bien este código puede responder a la pregunta, proporcionar un contexto adicional con respecto a por qué y/o cómo responde este código a la pregunta mejora su valor a largo plazo. – NathanOliver

Cuestiones relacionadas