是否可以在C ++类中使用信号?

时间:2008-12-05 08:42:56

标签: c++ signal-handling

我正在做这样的事情:

#include <signal.h>

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

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

}

我正在使用gcc在Ubuntu上工作。

但它不会编译。它抱怨道:

  

错误:类型为void (MyClass::)(int)的参数与void (*) (int)

不一致

任何线索?或者也许只是我不能在课程中使用信号?信号是否仅允许在C中?

错误消息是近似翻译,因为我的编译器不是英文。

6 个答案:

答案 0 :(得分:37)

signal的第二个参数应该是一个指向接受int并返回void的函数的指针。您传递给signal的是指向成员函数的指针,该函数接受int并返回void(其类型为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 :(得分:9)

要传递指向方法的指针,它必须是静态方法,您必须指定类名。

试试这个:

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

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

您还应该阅读Baget提供的链接paragraph 33.2 in the C++ FAQ

答案 2 :(得分:1)

阅读以下部分(33.2):

C++ FAQ - pointers-to-members

答案 3 :(得分:1)

实际上,C ++信号处理程序不允许使用C和C ++中不存在的任何工具(除了在C ++ 11中它们可能使用原子),并且需要使用C链接。引用C++11 draft n3242第18.10节“其他运行时支持”[support.runtime](第8段),

  

C和C ++语言的通用子集包含所有声明,   可能出现在格式良好的C ++程序中的定义和表达式   以及符合C的程序。 POF(“普通老函数”)是一个   仅使用此公共子集中的功能的功能,但不使用此功能   直接或间接使用任何非POF的函数,除了它   可以使用第29条中定义的非成员函数的函数。所有   信号处理程序应具有C链接。可以用作信号的POF   符合C程序中的处理程序在生成时不会产生未定义的行为   用作C ++程序中的信号处理程序。任何其他功能的行为   在C ++程序中用作信号处理程序的是实现定义的。

(第29条是关于原子的。)

答案 4 :(得分: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();
 }
}

答案 5 :(得分:0)

你可以发布新的答案而不是评论现有的答案,这似乎很疯狂,但我们去了。

gekomad从2015年9月24日开始的答案就是我用来解决问题的答案。值得指出的是,只有def ngrams(seq, n): return [seq[i:i + n] for i in range(len(seq) - n + 1)] a = [1,2,1,3,2] print ngrams(a, 2) # [[1, 2], [2, 1], [1, 3], [3, 2]] 创建了一个实例时,这才会完全明显。否则,静态对象指针将指向其中一个实例(最近创建的),这可能不是所需的实例。

并且,如果它对其他人有用,则在几个答案中链接的FAQ问题的有效2018 URL是:

http://www.cs.technion.ac.il/users/yechiel/c++-faq/memfnptr-vs-fnptr.html