0

C ファイルを C++ ファイルに変換しようとしていますが、次の typedef の定義で引き続き問題が発生します。以下に、Ah、A.cpp、およびメイン クラスのコードとクラス構造を示します。コンパイルしようとすると、次のエラーが発生します。

 main.cpp|44|error: no matching function for call to ‘A::Signal(int, <unresolved overloaded function type>)’|
 main.cpp|44|note: candidate is:|
 A.h|115|note: void (* A::Signal(int, void (*)(int)))(int)|
 A.h|115|note:   no known conversion for argument 2 from ‘&lt;unresolved overloaded function type>’ to ‘void (*)(int)’|

//ああ

class A
{
  public:
  void sigquit_handler (int sig);
  typedef void handler_t(int);
  handler_t *Signal(int signum, handler_t *handler);
}

//A.cpp

/*
 * Signal - wrapper for the sigaction function
 */
 A::handler_t* A::Signal(int signum, A::handler_t *handler) {

   struct sigaction action, old_action;
   action.sa_handler = handler;
   sigemptyset(&action.sa_mask); /* block sigs of type being handled */
   action.sa_flags = SA_RESTART; /* restart syscalls if possible */
   if (sigaction(signum, &action, &old_action) < 0) {
       unix_error("Signal error");
   }

   return (old_action.sa_handler);
 }

/*
 * sigquit_handler - The driver program can gracefully terminate the
 *    child shell by sending it a SIGQUIT signal.
 */
 void A::sigquit_handler(int sig) {
     if (verbose)
        printf("siquit_handler: terminating after SIGQUIT signal\n");
     exit(1);
     }

//main.cpp

int main(int argc, char **argv) {

A a;
a.Signal(SIGQUIT, a.sigquit_handler);  /* so parent can cleanly terminate child*/
}

なぜこれが起こっているのか誰かが私に説明できますか? 問題は sigquit_handler(void) の戻り値の型と Signal の入力パラメータ (int, handler_t*) が原因だと思いますが、その理由がわかりません。


提案された編集:

//ああ

class A
{
  public:
  void sigquit_handler (int sig);
  typedef void (*handler_t)(int);
  handler_t Signal(int,handler_t);
}

//A.cpp

/*
 * Signal - wrapper for the sigaction function
 */
 handler_t A::Signal(int signum, handler_t handler){

   struct sigaction action, old_action;
   action.sa_handler = handler;
   sigemptyset(&action.sa_mask); /* block sigs of type being handled */
   action.sa_flags = SA_RESTART; /* restart syscalls if possible */
   if (sigaction(signum, &action, &old_action) < 0) {
       unix_error("Signal error");
   }

   return (old_action.sa_handler);
 }

/*
 * sigquit_handler - The driver program can gracefully terminate the
 *    child shell by sending it a SIGQUIT signal.
 */
 void A::sigquit_handler(int) {
     if (verbose)
        printf("siquit_handler: terminating after SIGQUIT signal\n");
     exit(1);
     }

//main.cpp

int main(int argc, char **argv) {

A a;
a.Signal(SIGQUIT, &sigquit_handler);  /* so parent can cleanly terminate child*/
}

エラー:

 main.cpp|44|error: ‘sigquit_handler’ was not declared in this scope|
4

2 に答える 2

5

この(間違った)行では、次のようになります。

typedef void handler_t(int);

関数へのポインタへの typedef を作成します。このためには、いくつかの括弧と星を追加する必要があります:

typedef void (*handler_t)(int);

しかし、本当に必要なのは、次のように行われるメンバー関数へのポインターの typedef です。

typedef return_type (class_type::* func_t)(arg);

次に (コードのコメントを参照):

// Second parameter is wrong: you need to use
//     A::handler_t
// instead of:
//     A::handler_t*
//
//      error here                        error here
//          v                                   v
A::handler_t* A::Signal(int signum, A::handler_t* handler)
{
    struct sigaction action, old_action; // 'struct' not needed in C++
    // these 2 variables are not initialized
    // (except if they have a default constructor).

    // ...

    return (old_action.sa_handler); // parenthesis not needed. old_action was not changed in this function
}

最後に、ポインターをメンバーに渡す方法を次に示します。

A a;
a.Signal(SIGQUIT, &A::sigquit_handler);

さて、別の問題:sigaction::sa_handlerはメンバーへのポインターではありません。したがって、sigquit_handlerクラスから移動してA、関数を変更する必要がありSignalます。

// A.h
class A
{
    public:
        typedef void (*handler_t)(int);
        handler_t Signal(int,handler_t);
};
void sigquit_handler(int);

// A.cpp
void sigquit_handler(int)
{
    // ...
}

A::handler_t A::Signal(int,handler_t)
{
    // ...
}

// main.cpp
int main()
{
    A a;
    a.Signal(SIGQUIT, &sigquit_handler);
}
于 2013-03-17T17:44:56.560 に答える
3

ここにはいくつかの問題があります。1 つは、関数へのポインターを使用しているが、それをメンバー関数に渡していることです。それらの2つは同じではありません。std::functionとを調べることをお勧めしますstd::bind

于 2013-03-17T17:46:05.720 に答える