37

我正在做这样的事情:

#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 中使用吗?

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

4

6 回答 6

44

signal 的第二个参数应该是一个指向接受 int 并返回 void 的函数的指针。您传递给信号的是一个指向接受 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);

但我认为,如果您最终使用最后一个解决方案,您可能应该考虑改变您的处理设计:-)!

于 2008-12-05T16:56:20.950 回答
11

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

试试这个:

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

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

您还应该阅读 Baget 提供的链接,即 C++ FAQ 中的第 33.2 段

于 2008-12-05T09:01:32.470 回答
3

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

C 和 C++ 语言的公共子集包括所有可能出现在格式良好的 C++ 程序和符合标准的 C 程序中的声明、定义和表达式。POF(“plain old function”)是仅使用来自该公共子集的特征的函数,并且不直接或间接使用任何不是 POF 的函数,除非它可以使用第 29 条中定义的非 POF 函数。成员函数。所有信号处理程序都应具有 C 链接。可用作符合 C 程序中的信号处理程序的 POF 在用作 C++ 程序中的信号处理程序时不会产生未定义的行为。在 C++ 程序中用作信号处理程序的任何其他函数的行为是实现定义的。

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

于 2012-01-31T19:55:23.260 回答
3
#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();
 }
}
于 2015-09-24T09:13:12.343 回答
1

您可以发布声誉低于评论现有答案所需的新答案,这似乎很疯狂,但我们开始了。

gekomad 2015 年 9 月 24 日的回答是我用来解决问题的答案。值得指出的是,只有当只有一个myClasscreated 实例时,这才会完全明显地起作用。否则,静态对象指针将指向可能不是所需的实例之一(最近创建的)。

而且,如果它对其他人有用,几个答案中链接的常见问题解答问题的有效 2018 URL 是:

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

于 2018-04-04T08:42:18.077 回答
0

您可以使用单例模式

    static MyClass &getInstance() {
    static MyClass instance;
    return instance;
于 2021-05-21T18:26:27.907 回答