总结:尽量避免使用函数指针.
函数名与函数指针
double foo(int a,int b);//函数声明,double foo(int,int)为函数原型 |
上面这行代码为 函数声明 ,foo
为 函数名 ,double (int,int)
为 函数签名.
函数名是一个标识符,它是不可赋值的,它是可调用的.
&foo
表示函数的地址,函数地址 也是可以调用的,例如:
(&foo)(1,2);//与foo(1,2)相同. |
由于&foo
表示foo
函数的地址,则&foo
的类型就是函数指针.函数指针指向函数签名相同的函数.
定义并初始化函数指针
double pam (int); |
可调用对象
可调用对象包括一切可以调用的对象或名称,它包括:函数名,函数指针,lambda表达式,函数对象,类的成员函数(需要绑定对象)等.
函数指针可以绑定函数名和函数指针,而不可以绑定其他可调用对象.
class foo{ |
而使用std::function<函数签名>
就可以绑定一切可调用对象.
std::function<double (int)> a=foo(); |
所以说,std::function<函数签名>
可以完美替代函数指针.
模板参数中的函数指针
在unordered_map<class _Key,class _Tp,class _Hash = hash<_Key>>
中,第三个模板参数,要求是一个可调用对象的类型
|
在上面代码中,myhash
是一个函数名,myhash
本身是一个可调用对象,但是我认为它是没有类型的,因为myhash
的类型应当是它的函数签名,但是:
size_t (const std::array<int, 26>&) hasher = myhash; |
这段代码是错误的,因为size_t (const std::array<int, 26>&)
不能作为类型 来定义对象,所以我认为函数名是没有类型的.
但是其余可调用对象都是有类型的:
size_t (* hasher) (const std::array<int, 26>&) = myhash; |
复杂的函数指针
阅读这一篇幅,需要您熟练掌握,C语言中的指针。
//一些函数原型 |
我们对于语法的了解不能仅仅潜于认识,对于这种
const double *(*(*pd)[3])(const double *,int) = &pa;
我们不光要认识,更要会使用,再次重温一遍,我们想要一个指向数组的指针,这个数组里的元素是函数指针。第一步,数组元素的类型是函数指针,所以壳子要有
const double *(* ···)(const double *,int)
第二步,指向数组的指针(*pd)[3]
,由于[]比*优先级高,所以我们必须采用(),否则*pd[3]
就是一个数组,数组的元素是指针。
第三步,结合得const double *(*(*pd)[3])(const double *,int) = &pa
使用typedef 简化
typedef const double *(* p_fun)(const double *,int); |
typedef
使得代码量减少很多,而且更容易理解