2008-12-05 2 views
26

я делаю что-то вроде этого:Можно ли использовать сигнал внутри класса C++?

#include <signal.h> 

class myClass { 

    public: 

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

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

    } 

Я работаю на Ubuntu, используя GCC.

Но он не компилируется. Жалуется на:

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

Любые подсказки? Или, может быть, я просто не могу использовать сигнал внутри классов? Разрешены ли сигналы только в C?

Сообщение об ошибке является приблизительным переводом, потому что мой компилятор не находится на английском языке.

+0

Учтите, что сигналы не потокобезопасны, так что вы не могли бы хотеть пересмотреть это, если necesarry – 2008-12-05 08:55:57

+0

Причины вы должны использовать статический метод (как описано ниже), является то, что для вызова метода вам нужен экземпляр класса (объекта). Невозможно передать объект в сигнал, поэтому он должен быть нормальным указателем функции (а не указателем метода). – 2008-12-05 17:27:07

+0

@Robert Gould: True; но на самом деле не имеет отношения к предмету. – 2008-12-05 17:28:19

ответ

35

Второй параметр сигнала должен быть указателем на функцию, принимающую int и возвращающую пустоту. То, что вы передаете, является указателем на функцию , принимающую int и возвращающую пустоту (ее тип равен void (myClass::*)(int)). Я вижу три возможности, чтобы преодолеть эту проблему:

1 - Ваш метод myHandler может быть статическим: это здорово, сделать его статическим

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

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

2 - Ваш метод не должен быть статичным: если вы» планируя использовать сигнал только с одним экземпляром, вы можете создать частный статический объект и написать статический метод, который просто вызывает метод на этом объекте. Что-то вдоль линий

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 - Тем не менее, если вы планируете использовать сигнал с несколькими экземплярами, вещи становятся более сложными. Возможно, решение будет хранить каждый экземпляр, который вы хотите управлять в статическом векторе, и вызов метода на каждом из них:

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; 
}; 

и где-то, сделать один вызов

signal(SIGIO, myClass::callHandlers); 

Но Я думаю, что если вы в конечном итоге используете последнее решение, вам, вероятно, стоит подумать об изменении дизайна обработки :-)!

1

Прочитайте этот следующий раздел (33.2):

C++ FAQ - pointers-to-members

+0

Ссылка сломанный, поэтому бесполезный ответ. – 2016-02-05 11:48:11

+0

ссылка как отправлено 6 лет назад! – Baget 2016-02-06 09:52:59

9

Чтобы передать указатель на метод, он должен быть статический метод, и вы должны указать имя класса.

Попробуйте это:

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

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

И вы также должны прочитать ссылку, поставляемый Багет, в paragraph 33.2 in the C++ FAQ.

1

На самом деле, обработчикам сигналов C++ не разрешено использовать какие-либо объекты, которые не присутствуют ни на C, ни на C++ (за исключением того, что в C++ 11 они могут использовать атомику) и должны использовать C-ссылку. Цитирование C++11 draft n3242 раздел 18.10   "Другая поддержка выполнения" [support.runtime] (пункт 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.

(пункт 29 будучи один на Атомикс.)

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(); 
} 
} 
Смежные вопросы