【发布时间】:2015-12-11 13:47:20
【问题描述】:
我正在尝试将成员函数作为函数指针传递,这样我就不需要依赖单例或全局函数来处理 Qt 5 中的 Qt 消息。据我所知,我的 std::function 是类型正确,签名正确,并且 bind 应该允许我插入隐式 this 指针,本质上将成员函数作为全局/非拥有函数传递。
void ProgramMessageHandler::setAsMessageHandlerForProgram() {
std::function<void(QtMsgType, const QMessageLogContext &, const QString &)> funcPtr;
funcPtr = std::bind(handleMessages, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
qInstallMessageHandler(funkPtr);
}
这不会编译。我可以成功创建我的 funcPtr 变量,但将其传递给 qInstallMessageHandler 函数会导致以下情况:
log\ProgramMessageManager.cpp:16: error: cannot convert 'std::function<void(QtMsgType, const QMessageLogContext&, const QString&)>' to 'QtMessageHandler {aka void (*)(QtMsgType, const QMessageLogContext&, const QString&)}' for argument '1' to 'void (* qInstallMessageHandler(QtMessageHandler))(QtMsgType, const QMessageLogContext&, const QString&)'
oldHandler = qInstallMessageHandler(hackedPointerToHandleFunction);
^
我已阅读:
how to pass a member function as a function pointer?
How do you pass a member function pointer?
How to pass a member function as a parameter to a function that doesn't expect it?
Get function pointer from std::function when using std::bind
但没有人帮助过我。
编辑:
所以有人说,如果没有单例或全局函数,这是不可能的……但为什么呢?具有相同签名的成员函数和全局函数之间的唯一区别是它们不具有相同的签名,有一个隐含的this 指针作为成员函数的第一个参数。
知道了,为什么我不能使用 std::bind 来弥补这个差距,通过说“我知道被调用的函数在所有其他函数之前接受 this 参数,强制它在那里,成为知道的东西关于this。这比单例要干净得多,而全局函数只是废话。
【问题讨论】:
-
函数指针(与函数对象不同)可以没有自己的状态,因此在
this指针中无处“堵塞”。 -
@ChrisDrew 但我的
std::function不是在跟踪它吗?我的印象是std::bind能够通过跟踪 extra 信息将不同的东西绑定在一起,例如this指针... -
是的,
std::function可以跟踪它。但是qInstallMessageHandler不需要std::function它需要一个函数指针。 -
@ChrisDrew 那么在
std::function中是否没有指向函数的函数指针,该函数在调用时会将调用 ++附加信息传递给我的成员函数? -
Bind 在语法上与您想要的不同,因为它返回一个对象而不是函数指针。您可以使用 bind 存储 memberFunction + 实例对,但为了激活 memberFunction 调用,您必须在 std::function 对象上调用成员运算符 (),这与通过函数指针调用函数不同。这就是您的编译器抱怨的原因。从理论上讲,您可以将对 operator() 的调用存储在另一个函数 X 中并将 X 传递给 qInstallMessageHandler,但同样,您有一个要避免的全局函数。