type casting function pointers
-
Why can I cast a pointer to a static non-class function to DWORD (for example), but not a pointer to a non-static class function? (The compiler generates an error if you try) ie: DWORD dw1 = (DWORD)fnStaticGlobalFunc; // OK DWORD dw2 = (DWORD)pMyClass->fnClassLocalFunc; // Error
-
Why can I cast a pointer to a static non-class function to DWORD (for example), but not a pointer to a non-static class function? (The compiler generates an error if you try) ie: DWORD dw1 = (DWORD)fnStaticGlobalFunc; // OK DWORD dw2 = (DWORD)pMyClass->fnClassLocalFunc; // Error
-
Sorry, didn't include it because this: c:\Documents and Settings\Martijnv\My Documents\Visual Studio Projects\TestWin32Console\TestWin32Console\TestWin32Console.cpp(193) : error C2440: 'type cast' : cannot convert from 'void (__thiscall X::* )(void)' to 'DWORD' There is no context in which this conversion is possible ...still doesn't tell me why I CAN cast the static global function to DWORD but CANNOT cast the non-static class member function.
-
Why can I cast a pointer to a static non-class function to DWORD (for example), but not a pointer to a non-static class function? (The compiler generates an error if you try) ie: DWORD dw1 = (DWORD)fnStaticGlobalFunc; // OK DWORD dw2 = (DWORD)pMyClass->fnClassLocalFunc; // Error
For non class functions, the compiler knows exactly where the function resides. For class members it doesn't. class base { public: virtual void fn() {} }; class derrived { public: virtual void fn() {} }; base *p = new derrived; DWORD dw = (DWORD)p->fn; // which fn??
-
For non class functions, the compiler knows exactly where the function resides. For class members it doesn't. class base { public: virtual void fn() {} }; class derrived { public: virtual void fn() {} }; base *p = new derrived; DWORD dw = (DWORD)p->fn; // which fn??
-
Sorry, didn't include it because this: c:\Documents and Settings\Martijnv\My Documents\Visual Studio Projects\TestWin32Console\TestWin32Console\TestWin32Console.cpp(193) : error C2440: 'type cast' : cannot convert from 'void (__thiscall X::* )(void)' to 'DWORD' There is no context in which this conversion is possible ...still doesn't tell me why I CAN cast the static global function to DWORD but CANNOT cast the non-static class member function.
Notice the
__thiscall X::
part of the type - that means the function is a member ofclass X
and takes aX*
parameter (which becomesthis
in the method). You can't cast that away.--Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | NEW!! PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
-
Why can I cast a pointer to a static non-class function to DWORD (for example), but not a pointer to a non-static class function? (The compiler generates an error if you try) ie: DWORD dw1 = (DWORD)fnStaticGlobalFunc; // OK DWORD dw2 = (DWORD)pMyClass->fnClassLocalFunc; // Error
C++ refuses to 'throw away' the class association of the non-static class method, which is what is happening in the example you give with the class method. The compiler basically says, "If I lose the class association for this method, I won't be able to tie this method back to an instance of the class." It's not an issue with the a global (i.e. non-class ) function because there is no class association. It's also not a problem with a static class method. Static class methods aren't much more than global functions that are 'hidden' inside a class namespace. They don't have an instance of the class associated with them when they are invoked. If you really, really, really need to get the value as a DWORD, you can use a union to get there.
class CSomeClass { public: void SomeMethod(); }; union { DWORD dwValue; void (CSomeClass::*pMethod)(); } Address; // Assume pSomeClass points to an instance of CSomeClass; Address.pMethod = pSomeClass->SomeMethod; // You can now retrieve the 'address' of SomeMethod using // Address.dwValue
Note that this technique is not implementation independent! Run on a machine that uses pointers that are not 32-bits and you have a problem. Regards, Dan Remember kids, we're trained professionals.
Don't try this at home! -
C++ refuses to 'throw away' the class association of the non-static class method, which is what is happening in the example you give with the class method. The compiler basically says, "If I lose the class association for this method, I won't be able to tie this method back to an instance of the class." It's not an issue with the a global (i.e. non-class ) function because there is no class association. It's also not a problem with a static class method. Static class methods aren't much more than global functions that are 'hidden' inside a class namespace. They don't have an instance of the class associated with them when they are invoked. If you really, really, really need to get the value as a DWORD, you can use a union to get there.
class CSomeClass { public: void SomeMethod(); }; union { DWORD dwValue; void (CSomeClass::*pMethod)(); } Address; // Assume pSomeClass points to an instance of CSomeClass; Address.pMethod = pSomeClass->SomeMethod; // You can now retrieve the 'address' of SomeMethod using // Address.dwValue
Note that this technique is not implementation independent! Run on a machine that uses pointers that are not 32-bits and you have a problem. Regards, Dan Remember kids, we're trained professionals.
Don't try this at home!Actually that won't work.. If I use the union solution posted previously my compiler (Visual Studio .NET 2003) complains: error C2475: 'CSomeClass::SomeMethod' : forming a pointer-to-member requires explicit use of the address-of operator ('&') and a qualified name An implementation according to the suggestion of the compiler seems to work though:
Address.pMethod = &CSomeClass::SomeMethod;
But now, where on earth did all the fuss about the this pointer go?? Did I just seem to have discarded it?? -
Actually that won't work.. If I use the union solution posted previously my compiler (Visual Studio .NET 2003) complains: error C2475: 'CSomeClass::SomeMethod' : forming a pointer-to-member requires explicit use of the address-of operator ('&') and a qualified name An implementation according to the suggestion of the compiler seems to work though:
Address.pMethod = &CSomeClass::SomeMethod;
But now, where on earth did all the fuss about the this pointer go?? Did I just seem to have discarded it??Well, look at that - another syntax / semantics change from VC++ 6 to 2003/2005. Grumble, grumble, grumble... But yes, I just tried the variation you describe under 2005 and it does the trick. Anyway, it's not that you are discarding a specific 'this' pointer. The issue is that you are not discarding the class association. If you try to cast &CSomeClass::SomeMethod to something else such as:
DWORD dw = (DWORD) &CSomeClass::SomeMethod;
the compiler will still complain because this conversion would force it to discard the class association. (Actual error message under 2005 says,"There is no context in which this conversion is possible") Dan Remember kids, we're trained professionals.
Don't try this at home!