сигнал на C : использование функции-члена

#c #signals

#c #сигналы

Вопрос:

У меня такая проблема с signal() :

Этот код компилируется нормально:

 #include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void terminate( int param )
{
  printf ( "Terminating program...n" );
  exit( 1 );
}

int main()
{
    signal( SIGTERM, terminate );
    return 0;
}
  

Однако следующий код выдает эту ошибку:

 g   -Wall -c -g goober.cpp
goober.cpp: In member function `void GOOBER::yarrgh()':
goober.cpp:5: error: argument of type `void (GOOBER::)(int)' does not match `
   void (*)(int)'
make: *** [goober.o] Error 1
  

goober.h:

 #ifndef GOOBER_H
#define GOOBER_H

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

using namespace std;

class GOOBER {
public:
    GOOBER(){}
    ~GOOBER(){}
    void yarrgh();
    void terminate( int param );
};

#endif
  

goober.cpp:

 #include "goober.h"

void GOOBER::yarrgh()
{
    signal( SIGTERM, terminate );
}

void GOOBER::terminate( int param )
{
    printf( "Terminating program...n" );
    exit( 1 );
}
  

driver.cpp:

 #include "goober.h"

using namespace std;

int main()
{
    GOOBER G;
    G.yarrgh();

    return 0;
}
  

Я не вижу никакой разницы в коде, кроме того, что я вызываю signal() в члене. Есть идеи, что не так и как это исправить?

Ответ №1:

Вам нужно объявить свою terminate() функцию как static :

 class GOOBER {
    // ...
    static void terminate(int param);
};
  

Это связано с тем, что, будучи нестатической функцией-членом, terminate() функция ожидает, что ей будет передан (скрытый) this параметр, указывающий на некоторый экземпляр объекта. Поскольку механизм сигналов не знает об этом (или о чем-либо еще в C ), вам нужно использовать static функцию, чтобы не было скрытого this параметра.

Комментарии:

1. Я бы не доверял статическому члену иметь правильные требования к связыванию для функции C.

Ответ №2:

Я могу сказать вам, что не так:

Вы не можете использовать нестатическую функцию-член как обычный указатель на функцию. Функции-члены всегда имеют неявный this аргумент, который предоставляется (неявно) вызывающей стороной. C API не может этого сделать.

Ответ №3:

Terminate должна быть статической функцией в классе.

Ответ №4:

Сигнатура функции-члена отличается от обычной функции, которая не принадлежит ни одному классу. Однако статическая функция-член имеет ту же сигнатуру, что и обычная функция. Итак, вы могли бы объявить свою функцию-член terminate в классе GOOBER как статическую.