类的成员函数指针作为参数传递给其他函数和普通函数指针的传递是不同的
- 普通函数指针的传递只要在参数声明中声明是相同参数个数、类型和相同返回类型的函数指针,可是传递类成员函数指针用此方法却不能工作。
- 指针是指向一些内存地址的变量,既可以是数据的地址也可以是函数的地址。C++的 成员指针遵从同样的原则。但在类内部没有地址;选择一个类的成员意味着在类中偏移。只有把这个偏移和具体对象的开始地址结合,才能得到实际地址。类非静态成员函数指针的语法要求选择一个对象的同时引用成员指针。
- 类的静态成员函数采用与一般函数指针相同的调用方式,而受this指针的影响,类的非静态成员函数与一般函数指针是不兼容的。而且,不同类的this指针是不一样的,因此,指向不同类的非静态成员函数的指针也是不兼容的。指向类的非静态成员函数的指针,在声明时就需要添加类名。
- 可以用仿函数、lambda以及function实现函数指针的功能
完整的例子:
#include <iostream>
#include <functional>
using namespace std;
typedef void (*Pfun)(int, int); // 转义
typedef std::function<void(int, int)> functionType;
void fun1(int x, int y)
{
std::cout << x + y << std::endl;
}
void callFun(Pfun pfun)
{
pfun(2, 3);
}
void callFun1(Pfun pfun, int x, int y)
{
pfun(x, y);
}
class A
{
public:
int fun2(int x, int y)
{
return x * y;
}
static void staticFun(int x, int y)
{
std::cout << x - y << std::endl;
}
};
typedef int (A::*PClassFun)(int, int); // 转义
void callClassFun(A *a, PClassFun pclassfun)
{
// 方式1
int m = (a->*pclassfun)(4, 5);
std::cout << m << std::endl;
}
void callClassFun1(A &a, PClassFun pclassfun)
{
// 方式2
int m = (a.*pclassfun)(5, 6);
std::cout << m << std::endl;
}
void callClassFun2(void *context, PClassFun pclassfun, int x, int y)
{
// 方式3
A *a = reinterpret_cast<A *>(context);
int m = (a->*pclassfun)(x, y);
std::cout << m << std::endl;
}
typedef std::function<int(int, int)> ClassFunctionType;
int main()
{
// ---- 普通函数指针
// 普通调用
void (*p)(int, int); // 声明
//Pfun p; // 这样也可以
p = fun1; // 这里跟p = &fun1 是一样的
p(1, 2); // (*p)(1, 2) 调用是一样的
// 传参调用
callFun(fun1);
callFun1(fun1, 1, 1);
// C++11功能类
//std::function<void(int, int)> ft = fun1; // 声明定义
functionType ft1 = fun1; // 同样可以用转义
ft1(11, 12);
// ---- 类成员函数指针
// 普通类函数调用
int (A::*classFun)(int, int); // 声明
classFun = &A::fun2; // 这里必须用&符号
A a;
int m = (a.*classFun)(3, 4);
std::cout << m << std::endl;
// 静态类函数调用(跟普通函数类似,不用指定调用类实例)
Pfun q = A::staticFun; // Pfun q = &::staticFun一样
q(10, 5);
// 传参调用
callClassFun(&a, classFun);
callClassFun1(a, classFun);
callClassFun2(&a, classFun, 7, 8);
// C++11功能类
A b;
std::function<int(int, int)> ft2 = std::bind(&A::fun2, &b, std::placeholders::_1, std::placeholders::_2);
int res = ft2(9, 10); // 跟bind联合,用占位参数指定调用的参数, _1对应9, _2对应10
std::cout << res << std::endl;
return 0;
}
1,类的静态成员函数指针定义和使用方法跟普通函数指针几乎一样,因为静态类成员属于全局静态区存储
2,类的非静态类成员函数指针调用时需要指定哪个实例调用,所以需要额外传入类的实例(对象、引用、指针均可)上下文context
3,用function类实现的时候,不需要传入类实例上下文,因为bind里面已经做了绑定