C++ 在一个类中使用成员函数的泛型std::function对象
对于一个类,我想在一个C++ 在一个类中使用成员函数的泛型std::function对象,c++,function,function-pointers,c++11,tr1,C++,Function,Function Pointers,C++11,Tr1,对于一个类,我想在一个map存储std::function对象中存储一些指向同一类的成员函数的函数指针。但我一开始就失败了,代码如下: #include <functional> class Foo { public: void doSomething() {} void bindFunction() { // ERROR std::function<void(void)> f =
map
存储std::function
对象中存储一些指向同一类的成员函数的函数指针。但我一开始就失败了,代码如下:
#include <functional>
class Foo {
public:
void doSomething() {}
void bindFunction() {
// ERROR
std::function<void(void)> f = &Foo::doSomething;
}
};
#包括
福班{
公众:
void doSomething(){}
void bindFunction(){
//错误
std::function f=&Foo::doSomething;
}
};
我收到错误C2064:term未计算为在xxcallobj
中包含0个参数的函数,并伴有一些奇怪的模板实例化错误。目前,我正在使用VisualStudio2010/2011开发Windows8,使用VS10开发Win7,但也失败了。这个错误必须基于一些奇怪的C++规则,我不遵守< p>或者你需要< /p>
std::function<void(Foo*)> f = &Foo::doSomething;
必须使用对象调用非静态成员函数。也就是说,它总是隐式地传递“this”指针作为其参数
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
由于您的std::function
签名指定您的函数不接受任何参数(
),因此必须绑定第一个(也是唯一一个)参数
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
std::function f=std::bind(&Foo::doSomething,this);
如果要使用参数绑定函数,则需要指定占位符:
using namespace std::placeholders;
std::function<void(int,int)> f = std::bind(&Foo::doSomethingArgs, this, std::placeholders::_1, std::placeholders::_2);
使用名称空间std::占位符;
std::function f=std::bind(&Foo::doSomethingArgs,this,std::占位符::_1,std::占位符::_2);
或者,如果编译器支持C++11 lambdas:
std::function<void(int,int)> f = [=](int a, int b) {
this->doSomethingArgs(a, b);
}
std::函数f=[=](int a,int b){
这->doSomethingArgs(a,b);
}
(我手头没有支持C++11的编译器,因此无法检查此编译器。)如果需要在不存储类实例的情况下存储成员函数,可以执行以下操作:
class MyClass
{
public:
void MemberFunc(int value)
{
//do something
}
};
// Store member function binding
auto callable = std::mem_fn(&MyClass::MemberFunc);
// Call with late supplied 'this'
MyClass myInst;
callable(&myInst, 123);
std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable
如果没有auto,存储类型会是什么样子?
大概是这样的:
class MyClass
{
public:
void MemberFunc(int value)
{
//do something
}
};
// Store member function binding
auto callable = std::mem_fn(&MyClass::MemberFunc);
// Call with late supplied 'this'
MyClass myInst;
callable(&myInst, 123);
std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable
std::\u Mem\u fn\u wrap可调用
还可以将此函数存储传递给标准函数绑定
std::function<void(int)> binding = std::bind(callable, &testA, std::placeholders::_1);
binding(123); // Call
std::function binding=std::bind(可调用,&testA,std::占位符::_1);
有约束力(123);//呼叫
过去和将来的注意事项:存在一个较旧的接口std::mem_func,但后来被弃用。在C++17之后,有一个提议要提出。这将是非常受欢迎的。如果您希望在引擎盖下使用不太通用且更精确的控制,可以使用函子。使用win32 api将api消息从一个类转发到另一个类的示例
IListener.h
祝大家好运,感谢大家分享知识。
< P>不幸的是,C++不允许你直接获得一个对象和一个成员函数的可调用对象。code>&Foo::doSomething
为您提供了一个“指向成员函数的指针”,它引用的是成员函数,而不是关联的对象
有两种方法,一种是使用std::bind
将“指向成员函数的指针”绑定到this
指针。另一种方法是使用lambda捕获this
指针并调用成员函数
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
std::function<void(void)> g = [this](){doSomething();};
std::function f=std::bind(&Foo::doSomething,this);
函数g=[this](){doSomething();};
我更喜欢后者
使用g++时,至少将一个成员函数绑定到该函数将导致对象大小为三个指针,将其分配给std::function
将导致动态内存分配
另一方面,捕获此
的lambda大小仅为一个指针,将其分配给std::function
不会导致使用g++进行动态内存分配
虽然我还没有与其他编译器验证过这一点,但我怀疑会在那里找到类似的结果。您可以避免
std::bind
这样做:
std::function f=[this]->{Foo::doSomething();}
由于我不依赖boost,因此我将使用lambda表达式;)不过谢谢@AlxB: Boo..Bin不使用占位符的ADL,它将它们放在匿名命名空间中。我建议避免全局捕获[],并使用[S]来明确捕获的内容(Scott Meyers -有效的现代C++第6章。第31条-避免默认捕获模式)只需添加一点提示:成员函数指针可以隐式转换为std::function
,并将额外的this
作为第一个参数,如std::function=&Foo::doSomethingArgs
@landerYoung:添加函数名,如上面的“f”,以修复示例语法。如果您不需要名称,可以使用mem_fn(&Foo::doSomethingArgs)。@Danhstd::mem_fn
未删除;一堆不必要的重载被删除了。另一方面,std::mem_-fun
被C++11弃用,将被C++17删除。@Danh这正是我要说的;)第一个“基本”重载仍然存在:template unspecified mem_fn(rt:*)代码>,它不会消失。@Danh仔细阅读。博士删除了13个重载中的12个。最后一个重载不是(也不会是;在C++11或C++14中都不是)。为什么投反对票?其他每个响应都说必须绑定类实例。如果要为反射或脚本创建绑定系统,则不希望这样做。这个替代方法对某些人来说是有效的和相关的。谢谢Danh,我编辑了一些关于过去和未来相关接口的评论。谢谢你给出了这个很棒的答案:D正是我所需要的,我找不到如何专门化std::函数来调用任何类实例上的成员函数。这是编译的,但它是标准的吗?你保证第一个参数是这个?@sudorm rfslash是的,谢谢你的回复@ArmenTsirunyan。。。我可以在标准中的何处查找此信息?
class Button {
public:
Dispatcher _dispatcher;
//button window forward all received message to a listener
LRESULT onMessage(HWND hWnd, UINT uMsg, WPARAM w, LPARAM l) {
//to return a precise message like WM_CREATE, you have just
//search it in the map.
return _dispatcher[uMsg](hWnd, uMsg, w, l);
}
};
class Myclass {
Button _button;
//the listener for Button messages
LRESULT button_listener(HWND hWnd, UINT uMsg, WPARAM w, LPARAM l) {
return 0;
}
//Register the listener for Button messages
void initialize() {
//now all message received from button are forwarded to button_listener function
_button._dispatcher.add(WM_CREATE, this, &Myclass::button_listener);
}
};
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
std::function<void(void)> g = [this](){doSomething();};