之前一直以为C++成员函数没法取地址,一直使用静态函数来充当回调函数,直到近日看别人的代码才发现类成员函数也有指针。。。总结记录一下。
普通函数指针
这面是普通函数的指针的使用方法。
#include <stdio.h>
void printSum(int a, int b) {
printf("%d + %d = %d\n", a, b, a+b);
}
int main() {
// 声明一个函数指针变量,和声明一个普通变量类似,只是需要把这个变量名字放在这一串字符中间而已。
void (*sum)(int, int);
sum = &printSum; // 带不带&符号都一样效果,函数名也表示地址。
// sum = printSum; // 也可以这样
sum(1, 2);
printf("%p %p \n", printSum, &printSum); // 打印出来的地址是一样的,所以上面加不加&符号效果都一样
printf("%p %p \n", sum, *sum);
return 0;
}
输出
1 + 2 = 3
0x10162ded0 0x10162ded0 // 输出的四个地址都是一样的
0x10162ded0 0x10162ded0
关于 typedef 函数指针类型
可以对照普通用法看一看
// 直接声明变量
int i = 1;
void (*sum)(int, int) = printSum;
// 使用typedef
typedef int INT;
INT a = 1;
typedef void (*SUM)(int, int);
SUM fun = printSum;
类成员函数指针
与普通成员函数指针相比,类成员函数指针必须加上类名::
。
#include <stdio.h>
class Sample {
public:
void printSum(int a, int b){
printf("%d + %d = %d\n", a, b, a+b);
}
};
int main() {
void (Sample::*sum)(int, int);
sum = &Sample::printSum; // 这个必须加&,与普通函数不同
Sample *ins = new Sample;
(ins->*sum)(1, 2); // 注意:这里需要加星*
printf("%p", &Sample::printSum);
return 0;
}
输出
1 + 2 = 3
0x10300ef40
typedef 成员函数指针类型
typedef void (Sample::*SUM)(int, int);
SUM sum = &Sample::printSum;
总结
还是以上面的代码函数的定义为例:
- 普通成员函数的类型为
void (*)(int, int)
,类成员函数类型为void (Sample::*)(int, int)
,后者一定要加类名。 - 函数指针的定义和普通函数类似,区别是普通函数的变量名写在类型后面,函数指针类型变量名写在类型中间。
- 普通函数的函数名可以作为函数入口指针,加不加
&
符号都一样效果,类成员函数的指针必须加&
符号,调用的时候也必须加*
。 可以理解为普通函数名字等同于地址,成员函数的名字和地址不是一个东西。
代码在Mac gcc测试通过,有问题欢迎交流。