禁用“错误的函数转换”警告

11

我收到了以下警告:

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

这是因为我需要传递一个成员函数而不是普通函数作为参数。但程序运行正常。

我想要禁用此警告(Wno-bad-function-cast 对于C++无效),或者实现另一种方法来传递成员函数。


告诉我们你想做什么。很好,你不能禁用这个警告。将指向成员函数的指针传递给期望函数指针的东西是没有意义的(而且可能是未定义行为或其他问题)。 - R. Martinho Fernandes
你肯定需要重构代码,因为你正在将非静态函数成员传递给检索指向静态函数的方法或函数。 - zabulus
这真的是一个“错误的函数转换”警告吗?某些版本的GCC明确指出哪个警告标志是相关的。根据源代码,“错误的函数转换”只会在您转换函数调用的直接返回值时发生。 - skyking
3个回答

17

不要 忽视这个警告,你应该修改你的代码来处理这种情况。

成员函数指针 (void (MyClass::*)(byte)) 和普通函数指针 (void (*)(byte)) 是完全不同的。查看此链接。你不能直接将它们强制转换。否则会导致未定义行为或崩溃。

请看这里,它们的区别:

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

现在你可能会觉得,foo(byte)MyClass::foo(byte)具有相同的签名,那么为什么它们的函数指针不相同呢?这是因为,MyClass::foo(byte)在内部被解析为某种程度上,如下所示:

void foo(MyClass* const this, byte);

现在你可以嗅出它们之间的区别。

将成员函数指针声明为:

void (MyClass::*ptr)(byte) = &MyClass::foo;
你需要使用ptrMyClass对象一起使用,例如:
MyClass obj;
obj.*ptr('a');

好的,我会尝试解决这个问题... 我有一个函数(针对C而非C++),它接收一个指向普通函数的指针:void (*)(byte) 我该如何使它调用非静态对象的成员函数? - funkadelic
@funkadelic,请查看我的编辑帖子以了解成员函数指针的用法。在互联网上搜索更多类似的结果:http://www.codeproject.com/KB/cpp/FastDelegate.aspx - iammilind
1
在主要的差异中,成员函数指针与普通函数指针相比可能具有不同的物理大小,特别是如果它们指向虚方法。你可以问,“我如何将这12个字节转换为4个字节” - 如果你强制转换,这不会很好看。 - stusmith

0

你不能将需要两个参数的函数传递到只接受一个参数的函数中。这是不可能的,别想了,就这样吧。调用者向你的函数传递一个参数。它不知道第二个参数,也不会将其传递给你的函数,无论你如何努力,都无法让它按照你想要的方式运行。

出于同样的原因,你也不能将非静态成员函数传递到期望常规函数的位置。成员函数需要一个对象来操作。调用你的函数的任何代码都不知道这个对象,没有办法将其传递给它,也没有办法使其使用正确的调用序列,考虑到对象。

接受用户函数的接口,而不带有用户可能想要传递给他的函数的其他数据,本质上是邪恶的。看看C标准库中的qsort()函数。这是一个邪恶接口的例子。假设你想根据外部定义的排序方案对字符串数组进行排序。但它只接受一个比较函数,该函数接受两个值。如何将该排序方案传递给您的比较函数?你不能,所以如果你想让它工作,你必须使用一个邪恶的全局变量,附带所有的字符串。

这就是为什么C++已经逐渐远离传递函数指针,并转向函数对象。函数对象可以封装任何你想要的数据。

-2

另外,this 可能会有所帮助

union FuncPtr    
{
  void (* func)(MyClass* ptr, byte);
  void (MyClass::* mem_func)(byte);
};

这只是在招惹麻烦,除非你在某个地方存储一个标签,以表明哪个指针是有效的。具体来说,即使它避免了编译器警告,一个union也不能帮助把一个指针视为另一个类型的指针。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接