通常,我可以将函数对象分配给函数指针吗?我想做这样的事情:
#include <iostream>
class Foo {
int num;
public:
Foo(int num_par) : num(num_par) {}
void operator()(int multiplier) {
std::cout << multiplier * num << std::endl;
}
};
int main() {
typedef void(*bar)(int);
Foo f(42);
bar b = f; // MSVC error
// ^ C2440: 'initializing' : cannot convert from 'Foo' to 'bar'
b(2); // wanted to print 84
}
如果那是不可能的,我想要一个专门针对Windows编程的替代方案,我希望WindowProc
包含从WinMain
的正文数据设置的状态信息(即没有制作全局变量)。分配给WNDCLASSEX
的{{1}}成员时会出现此问题。虽然lpfnWndProc
解决了上述代码段的问题:
std::function
它对我的WinAPI案例不起作用:
std::function<void(int)> sf = f;
sf(2); // prints 84
MSVC 2013错误:
1。)错误C2440:class WindowProc {
int some_state;
public:
void set_some_state(int par);
LRESULT CALLBACK operator()(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
};
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
HWND hWnd;
WNDCLASSEX wc;
WindowProc wp;
typedef LRESULT(CALLBACK *baz)(HWND, UINT, WPARAM, LPARAM);
std::function<baz> std_func = wp;
std::function<baz> std_binded_func = std::bind(&WindowProc::operator(), &wp);
// none of these compile:
wc.lpfnWndProc = wp; // #1
wc.lpfnWndProc = wp.operator(); // #2
wc.lpfnWndProc = &WindowProc::operator(); // #3. Wrong anyway because some_state's value is part of the instance, not the class
wc.lpfnWndProc = std_func; // #4. Wrong anyway because some_state's value is part of the instance, not the class
wc.lpfnWndProc = std_binded_func; // #5
// do stuff...
wp.set_some_state(some_runtime_number);
// ...do other stuff
}
:无法从=
转换为WindowProc
2。)错误C3867:WNDPROC
:函数调用缺少参数列表;使用WindowProc::operator ()
创建指向成员的指针
2续。)错误C2440:&WindowProc::operator ()
:无法从=
转换为LRESULT (__stdcall WindowProc::* )(HWND,UINT,WPARAM,LPARAM)
3。)与&#39; 2续。&#39;
相同 4.。)错误C2440:WNDPROC
:无法从=
转换为std::function<baz>
5.)与4相同。
我怎样才能让它发挥作用?
答案 0 :(得分:2)
通常,除了要调用的函数之外,函数对象还包含其他上下文信息。关于可以分配给函数指针的唯一函数对象是带有空捕获的lambda函数,但这实际上只是一个函数:
void (*bar)(int) = [](int x) { std::cout << x; }
如果你想通过函数指针获取一个函数对象,你需要希望函数指针有一个合适的参数,供用户指定,哪些可以直接传递:
void call_function(int arg, void* user_data) {
(*static_cast<std::function<void(int)>*>(userdata))(arg);
}
...
std::function<void(int)> function_object;
void (*bar)(int, void*) = &call_function;
bar(17, &function_object);
最合理的现代接口采用函数指针也采用用户数据指针,可用于传递必要的上下文。显然,除了通过必要的上下文之外,可能还需要以某种方式维护用作上下文的对象的生命周期。
我不是Windows程序员,但我猜你正在尝试使用的API实际上能够设置函数指针和指向某些用户数据的指针。如果没有地方可以传递上下文信息,则需要以某种方式在函数指针本身中编码必要的信息。例如,您可以使用引用全局对象的函数指针来获取上下文。显然,您需要为要传递的每个上下文使用不同的函数。
答案 1 :(得分:1)
您需要以通常的方式声明指向成员函数的指针,然后调用它。试试这个:
#include <iostream>
class Foo {
int num;
public:
Foo(int num_par) : num(num_par) {}
void operator()(int multiplier) {
std::cout << multiplier * num << std::endl;
}
};
int main() {
typedef void(Foo::*bar)(int);
Foo f(42);
bar b = &Foo::operator(); // no more MSVC error
// ^ C2440: 'initializing' : cannot convert from 'Foo' to 'bar'
(f.*b)(2); // wanted to print 84, and it does
}
您必须通过实例化来调用它,在此示例中为f
。