0

I am trying to convert a C file in a C++ file, and I keep having problems with the following definition of typedef. Below I have shown the code and my class structure for A.h, A.cpp and my main class. When I try to compile, I get the following errors:

 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 ‘<unresolved overloaded function type>’ to ‘void (*)(int)’|

//A.h

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*/
}

Can someone explain to me why this is happening? I think that the problem is because of the return type of sigquit_handler(void) and the input parameter of Signal (int, handler_t*) but I can not understand why.


EDITS as suggested:

//A.h

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*/
}

Error:

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

2 Answers 2

5

I assume that with this (wrong) line:

typedef void handler_t(int);

You want to make a typedef to a pointer to function. For this, you have to add some parenthesis and a star:

typedef void (*handler_t)(int);

But what you really need is a typedef for a pointer to a member function, which is done like this:

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

Then (see code comments):

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

Finally, here is how to pass a pointer to member:

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

Now, another problem: sigaction::sa_handler is not a pointer to member. So, you need to move sigquit_handler out of class A, and change the function 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);
}
Sign up to request clarification or add additional context in comments.

12 Comments

If I do: typedef void (*handler_t)(int); I get a similar error: A.h|115|note: no known conversion for argument 2 from ‘<unresolved overloaded function type>’ to ‘void (**)(int)’|
Yes, see the rest of my answer, you need a typedef to a pointer to member : typedef void (A::* handler_t)(int);
See my edit, you had an exta star in one of the parameters of Signal.
Edited, you need to use a free function, not a member, for the signal handler.
Well, you didn't move sigquit_handler out of the class A. You have to do it.
|
3

You have a couple of problems here, one being that you use a pointer to a function, but passes it a member function. Those two are not the same. I suggest you look into std::function and std::bind.

1 Comment

for the second problem, my bad, I forgot to add it to the description above; I will edit it now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.