在学习ns3的道路上遇到了很多回调和函数指针相关的内容。
- 函数指针
int (*cmpFcn)(const char *, const char *);
假设还有个函数 int commonFun (const char *, const char *)
那么 cmpFun = &commonFun
讲道理我们要这样调用函数:
int result=(*cmpFcn)(a,b);
但实际上我们写成
int result=cmpFcn(a,b);
也可以,因为聪明的编译器知道我们在做什么。
- typedef函数指针
typedef int (*cmpFcn2)(const char *, const char *);
该定义表示cmpFcn是一种指向函数的指针类型的名字。要使用这种指针类型时只需直接使用cmpFcn即可,不必每次把整个声明都写出来。
所以可以有 cmpFcn2 PointFun=cmpFun
- 指向类成员函数的函数指针
原理差不多,但是声明和使用的格式稍微要注意一点
class A{
int member(int para){}
}
int (A::*pfi) (int xx) = &A::member ; //声明的时候
A a;
int sth=1;
( a.*pfi )( sth ); //使用的时候
思考下为什么类成员函数的函数指针一定要用一个类的对象来调用?因为该类不是静态成员函数啊,不可能脱离对象存在的。
那么静态成员函数可以直接通过类来调用吗?没实验过,但是想来是可以的。
小tip :PFI 是Pointer-of-Function-returning-Integer的缩写
attention:
- 定义指向类成员函数的函数指针的时候要声明类名( 如int (A::*pfi) (int xx) = &A::member ; ),使用的时候还要a.*pfi,因为你是一个指针,你本身(pfi)不是函数入口地址,你指向的地址(*pfi)才是函数入口地址。
- typedef的命名规则
- 其实替换简单数据类型的时候还是很直观的,比如说
但是定义数组和函数指针的时候就有点绕:typedef char* char_p; char_p p1; # 定义一个char的函数指针
可以这么想,一个typedef定义出来的名称得能直接用,想想如果要能直接用的话,得把名字放在哪里,那么新的名字就放在哪里。比如说 a[5],正常定义的时候是 int a[5] , 那么想要定义一个int数组 new_name,就是替代a的位置,因为要保证new_name[3]能索引到。# 数组 typedef int INT_ARR[5]; INT_ARR a; # 相当于int a[5] # 函数指针 int hesy(int x){ return x; } typedef int (*pfi)(int); pfi traceback_int = hesy
函数指针也是这么想。
简单数据结构的重命名不能这么做,不然直接覆盖掉了的话,咋知道原本是啥哇。