Thread: casting a void* to a pointer to a member function

  1. #1
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    casting a void* to a pointer to a member function

    This is driving me nuts! Here's my problem, I'll illustrate by example here for clarity.
    In brief, what I want to do is pass the address of a member function of a child class into a function of it's base class.
    But the compiler insinuates that this just isn't possible because child::function does not match parameter parent::function.
    I have tried all sorts of casts but the compiler stands firm.
    So my idea was to define the parameter i the parent class as type void*.
    Inside the function, I could then cast the child::function into a parent::function beneath the prying eyes of the compiler, and thus go about my day.
    But now it just says "cannot convert 'function' from type 'void *' to type 'void (Parent::*)()'..."


    example:

    Code:
    class Parent {
    public:
    
    void (Parent:: *invoke)(void);
    
    void AttachA(void (Parent:: *function)(void)) {
    invoke = function;
    }
    
    void AttachB(void * function) {
    invoke = (void (Parent:: *)(void)) function;
    }
    };
    
    
    
    
    class Child : public Parent {
    public:
    
    void ThisFunction() {
    
     }
    
    
    void Attach() {
     
     AttachA(&Child::ThisFunction); //...error: no matching call to AttachA(void (Child::(*)())...(canidates are "Parent::")...
    
     AttachA(&Parent::ThisFunction); //...error: ThisFunction not a member of parent...
    
     AttachB((void*)ThisFunction); //..error: cannot resolve based on conversion to type void*...
    }
    
    };

    Anyone know a good way around that?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #2
    Cheesy Poofs! PJYelton's Avatar
    Join Date
    Sep 2002
    Location
    Boulder
    Posts
    1,728
    I had a similar problem once that might help you. I tried to make a menu class that allowed the user to take outside functions and add it to the menu list, but the compiler kept complaining about type mismatches. Someone recommended to me to make the attach functions static, and it worked beautifully!

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    well, except that a static member function is shared across all instances, which won't work here.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Excecute this line of code and you have your answer why it isn't possible:
    Code:
    cout << sizeof(void (Parent::*)()) << " " << sizeof(void*);
    It returns
    Code:
    12 4
    On my compiler.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708


    I wonder if this is possible:

    void AttachB(void * glob[3]) {
    invoke = (void (Parent:: *)(void)) glob;
    }


    ...nah
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Heh, I suppose you could use memcpy with the above function.

    Did you really need this feature or were you just curious if it could be done?
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Did you really need this feature or were you just curious if it could be done?
    Unfortunately, the implementation of that group of classes absolutely depends on it! (think linked lists )
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    More specifically, what are you trying to accomplish?
    There is always another solution...
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Well, essentially, I have a certain (1) sub-base class (for declarative purposes), and then (2) a container class which, among other things, stores pointers to functions of that sub-base class and child classes. (3) Then there is the next higher base class which contains a linked list of the helper objects, and a function to pass child function pointers to the helper objects.
    The problem is the C++ type-checking system. Not trusting that I won't pass a child function pointer to a parent object (thus crashing the system, I suppose), it refuses to compile! My only recourse seems to be working out a <tempate> scheme OR an ugly hack that I learned a while back that completely ruins the interface of the class.../*sigh*/...but yes, there must be some other way. I will research this further...

    Anyway, the Omicron project you're working on looks promising
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Smile got it.

    Code:
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~//
    
    class Parent {
    public:
    
    void (Parent:: *invoke)(void);
    
    void Attach(void (Parent:: *function)(void)) {
      invoke = function;
      }
    
    };
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~//
    
    class Child : public Parent {
    public:
    
    void ThisFunction() { }
    
    Child() { 
       Attach( static_cast<void(Parent::*)(void)>(&Child::ThisFunction) ); 
       }
    
    };
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~//
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #11
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Great, but why is a pointer to a member function 12 bytes anyway?
    Shouldn't 4 bytes be enough?
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Well, I assume it's because of naming conventions and so forth. You know, in C give a single function in our entire library a certain, unique name. C++ is of course quite different what with the ability to have 40 member functions with the same name! But that's a good question I should research...get back to you on that one...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #13
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    I've done some research, too.
    I used the following code to dump the memory of a variable.
    Code:
    #define print_size(a) cout << "sizeof("<< #a << ") = " << sizeof(a) << endl;
    #define print_dump(a) cout << "dump of "<< #a << " : "; my_dump(&a,sizeof(a)); cout << endl;
    void my_dump(void* var, unsigned size=12)
    {
        using namespace std;
        unsigned char * data = (unsigned char*) var;
        for (unsigned i = 0; i < size; ++i)
            cout << hex <<setw(2) << setfill('0') << (int)data[i] << " ";
    }
    Then I tried dumping pointer-to-member-function varibles using different class inheritance.
    The first 4 bytes was always 0x00000000 (use unknown).
    The next four bytes was always 0xffffffff unless the function was virtual.
    The last four bytes was the address to the function (I think).

    Pointer-to-member-variable was easier. They contain four bytes wich is the offset of the variable within the class + 1.
    The reason why it adds one is because zero is reserved as the null pointer.
    Last edited by Sang-drax; 10-15-2002 at 04:22 AM.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  14. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Hey, thanks. Great snooping there.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  4. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  5. Staticly Bound Member Function Pointers
    By Polymorphic OOP in forum C++ Programming
    Replies: 29
    Last Post: 11-28-2002, 01:18 PM