Подтвердить что ты не робот

Можно ли использовать сигнал внутри класса С++?

Я делаю что-то вроде этого:

#include <signal.h>

class myClass {

    public: 

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

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

    }

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

Но он не будет компилироваться. Он жалуется:

error: аргумент с типом void (MyClass::)(int) не согласуется с void (*) (int)

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

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

4b9b3361

Ответ 1

Второй параметр сигнала должен быть указателем на функцию, принимающую 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);

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

Ответ 2

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

Попробуйте следующее:

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

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

И вы также должны прочитать ссылку, предоставленную Baget, параграф 33.2 в FAQ по С++.

Ответ 4

Собственно, обработчикам сигналов С++ не разрешено использовать какие-либо объекты, которые не присутствуют ни на C, ни на С++ (за исключением того, что в С++ 11 они могут использовать атоматику) и должны использовать C-ссылку. Цитирование С++ 11 черновик n3242 раздел 18.10   "Другая поддержка времени выполнения" [support.runtime] (пункт 8),

Общее подмножество языков C и С++ состоит из всех объявлений, определения и выражения, которые могут отображаться в хорошо сформированной программе на С++ а также в соответствующей программе на С. POF ( "простая старая функция" ) является функция, которая использует только функции из этого общего подмножества, и это не прямо или косвенно использовать любую функцию, которая не является POF, за исключением того, что она могут использовать функции, определенные в разделе 29, которые не являются функциями-членами. Все обработчики сигналов должны иметь C-связь. POF, который может использоваться как сигнал обработчик в соответствующей программе C не создает поведение undefined, когда используемый в качестве обработчика сигнала в программе на С++. Поведение любой другой функции используемый в качестве обработчика сигнала в программе на С++, определяется реализацией.

(пункт 29 является тем, который является атоматикой.)

Ответ 5

#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();
 }
}