如何用std::函数编写指向成员函数的指针
How do i write a pointer-to-member-function with std::function?
我知道如何在std::function(std::function<int(double)>
)中声明int fn(double)
。我知道如何编写指向成员函数(typedef int (A::*MemFn)(double d);
)的指针。但是,如何用std::函数编写指向成员函数的指针呢?
如果您想编译/测试,请使用伪代码
-编辑-根据答案,我想我只需要使用typedef,而不需要使用std::函数
#include <cstdio>
#include <functional>
struct A{ int fn(double){ return 0; } };
int fn2(double){ return 0; }
typedef int (A::*MemFn)(double d);
typedef std::function<int(double)> MemFn2;
void Test(A*a, MemFn2 fn){
fn(1.2f);
}
void Test(A*a, MemFn fn){
(a->*fn)(1.2f);
}
int main(){
Test(new A, &A::fn);
Test(new A, &fn2);
}
std::function
完全能够直接存储成员函数指针。但是,您必须适当地调整参数列表。必须使用类型(或派生类型)的实例调用成员指针。将它们放在std::function
中时,参数列表中的第一个参数应该是指向对象类型的指针(或引用或智能指针)。
所以,如果我有以下类:
struct Type
{
public:
int Foo();
};
在std::function
中存储此成员函数的正确语法是:
std::function<int(Type&)> fooCaller = &Type::Foo;
如果要保留参数列表(在本例中为int(double)
),则需要在function
之外提供实例。这可以通过std::bind
:完成
struct A{ int fn(double){ return 0; } };
A anInstance;
std::function<int(double)> fnCaller = std::bind(&A::fn, &anInstance, std::placeholders::_1);
请注意,您有责任确保您提供给std::bind
的对象指针在fnCaller
处于活动状态时保持活动状态。如果您将fnCaller
返回给某人,而它有一个指向堆栈对象的指针,那么您就有麻烦了。
好的是,由于函数调用机制的定义,您可以将shared_ptr
(或任何可复制的智能指针)绑定为对象:
struct A{ int fn(double){ return 0; } };
auto anInstance = std::make_shared<A>();
std::function<int(double)> fnCaller = std::bind(&A::fn, anInstance, std::placeholders::_1);
现在你不必担心;绑定器将继续保持对象活动,因为它按值存储shared_ptr
。
成员函数不是函数。它本身不是任何你能称之为的东西。您所能做的就是调用实例对象的成员函数。只有指向成员函数和对象的指针对才构成可调用实体。
要将实例绑定到PTMF并获得可调用的内容,请使用bind
:
#include <functional>
struct Foo
{
double bar(bool, char);
};
Foo x;
using namespace std::placeholders;
std::function<double(bool, char)> f = std::bind(&Foo::bar, x, _1, _2);
f(true, 'a'); //...
与lambdas一样,绑定表达式具有未知类型,并且转换为std::function
(以及实际调度)可能代价高昂。如果可能的话,对于结合表达的类型,优选使用auto
。
Scott Meyer的《现代C++11》一书中的指导原则之一是避免使用std::bind
,并始终使用lambda闭包:
struct A{ int fn(double){ return 0; } };
std::function<int(double)> f = [a = A{}](double x) mutable { return a.fn(x); };
mutable
在这里是必要的,因为函数调用可能会更改捕获a
(因为A::fn
是非常数)。
您可以使用std::binder1st
将成员函数绑定到类实例:
typedef std::binder1st<std::mem_fun1_t<int, A, double>> MemFn;
void Test(A* a, double d)
{
MemFn fn(std::mem_fun(&A::fn), a);
int nRetVal = fn(d);
}
int main()
{
Test(new A, 1.2f);
return 0;
}
如果你可以使用Boost
,那么你就可以使用Boost.Bind
boost::bind(&MyClass::MemberFunction, pInstance, _1, _2)
希望这是不言自明的。_1
和_2
是可以传递给函数的参数的占位符。
- 如何使用指针传递给函数的数组中对象的函数成员
- c++构造函数成员初始化:传递参数
- 创建 std::函数,它返回具有函数成员值的变量.分段错误
- 如何在C++通过公共函数访问私有函数成员?
- 解释了构造函数成员初始化列表
- 调用std::函数成员时内存损坏
- 是否可以为模板类的模板函数成员设置别名?
- 捕获 lambda 函数C++成员变量
- 构造函数成员初始值设定项跨成员列出,安全吗?
- 获取与在模板参数中传递的函数成员类型相同的类
- 如何从公共函数成员访问地图私有成员
- C 构造函数成员分配优化
- 使用命名空间进行函数成员定义
- 函数成员作为 CUDA 内核的参数
- 模板基类函数成员的别名
- 函数成员中用于void和继承的enable_if
- 头文件中是否定义了一个很长的Class函数成员
- 类内/构造函数成员初始化
- 使用指向部分专用函数成员的指针自动填充向量
- 指向函数成员的指针