11

I'm receiving the following warning:

warning: converting from 'void (MyClass::*)(byte)' to 'void (*)(byte)'

This is because I need to pass as argument a member function instead of an ordinary function. But the program is running correctly.

I'd like to disable this warning (Wno-bad-function-cast doesn't work for C++) or to implement a different way to pass a member function.

funkadelic
  • 311
  • 1
  • 2
  • 10
  • Tell us what you're trying to do. It's a good thing you can't disable this warning. It doesn't make sense to pass a pointer to member function to something expecting a function pointer (and it's probably UB or something). – R. Martinho Fernandes Jul 13 '11 at 09:33
  • It's surely that you need to refactor code, because you are passing non static function member to the method or function that retreives pointer to static function – zabulus Jul 13 '11 at 09:38
  • Is that really a "bad function cast" warning? Some versions of GCC says explicitly which warning flag that is relevant. According to the source "bad function cast" should only happen if you convert the direct return value from a function call. – skyking Feb 10 '16 at 06:17

3 Answers3

17

No. Take this warning seriously. You should rather change your code to handle this scenario.

Pointer to member function(void (MyClass::*)(byte)) and normal function pointer (void (*)(byte)) are entirely different. See this link. You cannot cast them just like that. It results in undefined behavior or crash.

See here, how they are different:

void foo (byte); // normal function
struct MyClass {
  void foo (byte); // member function 
}

Now you may feel that, foo(byte) and MyClass::foo(byte) have same signature, then why their function pointers are NOT same. It's because, MyClass::foo(byte) is internally resolved somewhat as,

void foo(MyClass* const this, byte);

Now you can smell the difference between them.

Declare pointer to member function as,

void (MyClass::*ptr)(byte) = &MyClass::foo;

You have to use this ptr with the object of MyClass, such as:

MyClass obj;
obj.*ptr('a');
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • ok, I'll try to deal with the problem... I have a function (thought for C, more than for C++) which receives a pointer to ordinary function: void (*)(byte) How could I make it call a member function of a non-static object? – funkadelic Jul 13 '11 at 09:34
  • @funkadelic, see my edit post for the usage of function pointer to member. See on internet for more such results: http://www.codeproject.com/KB/cpp/FastDelegate.aspx – iammilind Jul 13 '11 at 09:43
  • 1
    Among the major differences, pointer to member functions are likely to be a different physical size compared to pointer to normal functions, especially if they point to a virtual method. You might as well ask, "how do I cast these 12 bytes to 4 bytes" - it's not going to be pretty if you force it. – stusmith Jul 13 '11 at 10:26
0

You can't pass a function that takes two arguments to a place that expects a function that takes one. Can't be done, forget about it, period, end of story. The caller passes one argument to your function. It doesn't know about the second argument, it doesn't pass it to your function, you can't make it do what you want however hard you try.

For the very same reason you can't pass a non-static member function where a regular function is expected. A member function needs an object to operate on. Whatever code calls your function doesn't know about the object, there's no way to pass it the object, and there's no way to make it use the right calling sequence that takes the object into account.

Interfaces that take user's functions, without taking additional data that the user might want to pass to his function, are inherently evil. Look at the qsort() function from the C standard library. That's an example of an evil interface. Suppose you want to sort an array of string according to some collation scheme defined externally. But all it accepts is a comparison function that takes two values. How do you pass that collation scheme to your comparison function? You can't, and so if you want it working, you must use an evil global variable, with all the strings attached to it.

That's why C++ has moved away from passing function pointers around, and towards function objects. Function objects can encapsulate whatever data you want.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
-2

Also, this may be helpful

union FuncPtr    
{
  void (* func)(MyClass* ptr, byte);
  void (MyClass::* mem_func)(byte);
};
Community
  • 1
  • 1
Chris Bednarski
  • 3,364
  • 25
  • 33
  • That's just asking for trouble, unless you're storing a tag somewhere saying which pointer is valid. Specifically, a `union` does not help treat one pointer as the type of the other, even if it avoids the compiler warning. – Ben Voigt Jul 20 '12 at 18:47