对于一个类,我想在一个存储std::function对象的映射中存储一些指向同一类的成员函数的函数指针。但我一开始就写错了这段代码:
#include <functional>
class Foo {
public:
void doSomething() {}
void bindFunction() {
// ERROR
std::function<void(void)> f = &Foo::doSomething;
}
};
我收到错误C2064: term没有在xxcallobj中计算为一个接受0参数的函数,并结合了一些奇怪的模板实例化错误。目前我正在用Visual Studio 2010/2011在Windows 8上工作,用VS10在Win 7上工作,它也失败了。这个错误一定是基于我没有遵循的一些奇怪的c++规则
如果你需要存储一个没有类实例的成员函数,你可以这样做:
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);
如果没有auto,存储类型会是什么样子?
就像这样:
std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable
还可以将此函数存储传递给标准函数绑定
std::function<void(int)> binding = std::bind(callable, &testA, std::placeholders::_1);
binding(123); // Call
过去和将来的注意事项:存在一个较旧的接口std::mem_func,但已弃用。在c++ 17之后,存在一个提议,将指向成员函数的指针设为可调用的。这将是最受欢迎的。
不幸的是,c++不允许直接获取引用对象及其成员函数之一的可调用对象。&Foo::doSomething给你一个“指向成员函数的指针”,它指向成员函数而不是关联对象。
有两种方法,一种是使用std::bind将“指向成员函数的指针”绑定到this指针。另一种是使用lambda来捕获this指针并调用成员函数。
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
std::function<void(void)> g = [this](){doSomething();};
我更喜欢后者。
在g++中,至少将一个成员函数绑定到this将导致一个对象大小的三指针,将this分配给std::函数将导致动态内存分配。
另一方面,捕获这个的lambda在大小上只有一个指针,将它赋值给std::函数不会导致g++的动态内存分配。
虽然我还没有与其他编译器验证这一点,但我怀疑在那里会发现类似的结果。
非静态成员函数必须与对象一起调用。也就是说,它总是隐式地传递“this”指针作为参数。
因为你的std::function签名指定你的函数不接受任何参数(<void(void)>),你必须绑定第一个(也是唯一的)参数。
std::function<void(void)> 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);
或者,如果你的编译器支持c++ 11 lambdas:
std::function<void(int,int)> f = [=](int a, int b) {
this->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);
如果没有auto,存储类型会是什么样子?
就像这样:
std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable
还可以将此函数存储传递给标准函数绑定
std::function<void(int)> binding = std::bind(callable, &testA, std::placeholders::_1);
binding(123); // Call
过去和将来的注意事项:存在一个较旧的接口std::mem_func,但已弃用。在c++ 17之后,存在一个提议,将指向成员函数的指针设为可调用的。这将是最受欢迎的。