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の2番目のパラメーターは、intを受け入れてvoidを返す関数へのポインターである必要があります。シグナルに渡すのは、intを受け入れてvoidを返すメンバーvoid (myClass::*)(int)関数へのポインターです(その型は)。この問題を克服するための3つの可能性を見ることができます。

1-メソッドmyHandlerは静的にすることができます:これは素晴らしいです、静的にします

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

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

2-メソッドは静的であってはなりません。1つのインスタンスのみでsignalを使用することを計画している場合は、プライベート静的オブジェクトを作成し、このオブジェクトのメソッドを呼び出すだけの静的メソッドを作成できます。の線に沿った何か

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

また、 C++ FAQのパラグラフ 33.2 である Baget によって提供されたリンクも読む必要があります。

于 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 ではない関数を直接的または間接的に使用することはありません。メンバー関数。すべてのシグナルハンドラは 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 に答える