LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C++ Signals and Member Pointers (https://www.linuxquestions.org/questions/programming-9/c-signals-and-member-pointers-429033/)

lackluster 03-27-2006 12:27 PM

C++ Signals and Member Pointers
 
I know this has been hashed over many times, but I can't seem to find a suitable answer. I don't understand why this doesn't work:

Code:

#include <signal.h>
#include <iostream>

using namespace std;

class SigHandler {
  typedef void (SigHandler::*Func)(int);
  typedef void (*CStyleFunc)(int);

public:
  SigHandler() {
    Func func = &SigHandler::OnControlC;
    CStyleFunc cFunc = this->*func;

    signal(SIGINT, cFunc);
  }

  void OnControlC(int) {
    cout << "Control-C" << endl;
  }
};

int main(int, char**) {
  SigHandler sig;
  int i = 0;

  while (1) {
    cout i++ << ".)" << endl;

    sleep(5);
  }

  return 0;
}

I have an associated object (this) so why does g++ complain:

Quote:

main.cpp:13: error: invalid use of non-static member function
What does it care? I have an associated object and a pointer to a member function that is equivalant to void (*)(int). There must be a way to do this without globals/static member.

ceros 03-27-2006 01:28 PM

You try a different release of g++, maybe g++ 3.4.x or 3.3.x?

graemef 03-27-2006 01:35 PM

maybe I missed something but what is this->*func? there is a local variable called func but I didn't see a member variable with that name.

graemef 03-27-2006 01:46 PM

I also think that line
Code:

Func func = &SigHandler::OnControlC;
should be
Code:

Func func = OnControlC;
and probably forget about cFunc.

sm1else 03-27-2006 01:52 PM

Quote:

Originally Posted by lackluster
What does it care? I have an associated object and a pointer to a member function that is equivalant to void (*)(int). There must be a way to do this without globals/static member.

I should point out that this will probably not be all that accurate, I dont know how g++ implements things.

You dont really have a pointer to the object. This is because the object pointer is not stored in cFunc, only the function pointer is (you would need two void*'s to store both and cFunc is only one).
In fact func and cFunc are identical in this code.

I think its because at runtime the compiler will be unable to identify your object using only the function pointer. As a result it wont know where to lookup member variables for any purpose (reading or writing). Note that it doesnt matter if you use any member variables or not because there will be some implicit variables which the compiler will add since they are needed on the stack (the 'this' pointer would be a good example).
The static keyword prevents the use of non-static member variables within the function. This removes the need to know where the particular object is stored in memory and prevents some of the implicit variables such as the 'this' pointer.

The normal way around is to ensure the contents of the 'this' pointer is passed as an argument to the static function. You can then use the argument to access the original object. However this wont work in this situation.

If there will only ever be one instance of SigHandler then you can build SigHandler as a singleton class. The idea is to store a pointer to the object in a static member variable (equivalent to 'this'). Then when your signal handler is called, you make it obtain the pointer to the actual object and use that.

Hope that makes sense

lackluster 03-27-2006 04:55 PM

sm1else, that's not a bad explanation. I thought that an address to a function should simply call that function and be done with it. Who cares if it's a member function or a function in another process? That's why I felt like I did have a pointer to the object. this is the object, pointing at the member function .. at this point I shouldn't need the object anymore - we're talking about a singular place in memory.

But what you're saying is that if I needed to access this->foo then it wouldn't know what the hell I was saying because wtf is this now, right? I guess without knowing the internals of exactly what happens when a class is compiled, this may be unsolvable for the desired method.

sm1else 03-28-2006 07:03 AM

Thats right, it knows 'this' at the time of assignment, but when it uses the function pointer it doesnt know 'this'. It's all down to the fact that C++ isnt purely object oriented, its really C but extended with classes and objects.

Glad I could help

ta0kira 03-29-2006 12:41 PM

This is one of those things where logic doesn't line up; you cannot bind a member function to an object in the way you can bind a data member to an object. Logic would say that since
Code:

//Data Member
int (Class::*) + Class* = int*

then this must also be true
Code:

//Member Function
void(Class::*)() + Class* = void(*)()

The reason you can bind a data member to an object is because there is actually a copy of that data member for each instance of the class; if a class contains an int, each object will have its own int, and all will have their own memory address, just like a global int will.

Member functions, however, only exist in a master table for the class; the actuall binary code for the function is not duplicated for each instance. For this reason, the function call needs a this pointer. In order to bind the two together, the program would have to turn the member function into a static function (by copying the binary code and doing some run-time recompilation), which is beyond the capability of pretty much any program.

What you need is a functor; this will allow you to bind a member function to an object and call it like a global function via an operator (). All you really need is a pointer to an object, a pointer to a member function, and an operator ().
ta0kira


All times are GMT -5. The time now is 02:51 PM.