C++ primer第六章6.7函数指针

函数指针

  • 函数指针指向的是函数而不是对象。和其他指针一样,函数指针指向某种特定的类型。函数的类型由他的返回类型和形参类型共同决定,而与函数的名字无关。
//比较两个string对象的长度
bool lengthCompare(const string &,const string &);
  • 要想声明一个可以指向该函数的指针,只需要指针替换函数的名字即可
  • pf的名字之前有一个* ,因此pf是指针;右侧是形参的列表,表示pf指向的是函数;观察左侧,发现函数的返回数值是bool类型的。因此,pf就是一个指向函数的指针,其中该函数的参数是两个const string的引用,返回的是bool类型。
//pf指向一个函数,该函数的参数是两个const string的引用,返回的数值是bool类型
bool (*pf)(const string &,const string &);//未初始化
  • *pf两端的括号不可以省略,如果没有这对括号,则pf是一个返回数值为bool的指针的函数
//声明一个名为pf的函数,该函数返回bool *
bool *pf(const string &,const string &);//未初始化

使用函数指针

  • 当把函数的名字作为一个数值进行使用的时候,该函数会自动地转化成指针。
//例如,按照如下的形式将lengthCompare的地址赋值给pf
//pf = lengthCompare; //pf指向名字为lengthCompare的函数
//pf = &lengthCompare;//等价的赋值语句,取地址符的符号是可选的
  • 还可以直接使用指向函数的指针调用该函数,而不需要提前解引用指针
bool b1 = pf("hello","goodbye"); //调用lengthCompare函数
bool b2 = (*pf)("hello","goodbye");//一个等价的调用
bool b3 = lengthCompare("hello","goodbye");//一个等价的调用
  • 指向不同函数类型的指针之间不存在转换的规则,但是我们可以为函数指针赋值一个nullptr或者数值为0的整型常量的表达式,表示这个指针没有指向任何一个函数

重载函数的指针

  • 当使用重载函数的时候,上下文必须界定该选用哪个函数。如果定义了指向重载函数的指针
void ff(int *);
void ff(unsigned int);
void (*pf1)(unsigned int) = ff;//pf1指向了ff(unsigned int)

函数的指针形参

  • 和数组类似,虽然不可以定义函数类型的形参,但是形参可以是指向函数的指针。此时形参看起来是函数的类型,实际上却是当成指针来使用
//第三个形参是函数类型,他会自动的转换成指针
void useBigger(const string &s1,const string &s2,bool pf(const string &,const string &));
//等价的声明:显式地将形参定义成指向函数的指针
void useBigger(const string &s1,const string &s2,bool (*pf)(const string &,const string &));
//可以把函数作为实参的使用,此时他会自动的转化成指针
useBigger(s1,s2,lengthCompare)
  • 可以使用类型的别名和decltype来简化使用函数指针的代码
//Func和Func2是函数的类型
typedef bool Func(const string & ,const string &);
typedef decltype(lengthCompare) Func2;  //等价的类型
//Funcp和Funcp2是指向函数的指针
typedef bool (*Funcp)(const string & ,const string &);
typedef decltype(lengthCompare) *Funcp2;  //等价的类型
  • decltype返回函数的类型,不会将函数的类型自动转化成为指针类型。因为,decltype的类型是函数类型,因此只有在前面加上*,才可以得到指针。
//usingBigger的等价声明,其中使用了类型的别名
void useBigger(const string &s1,const string &s2,Func);
void useBigger(const string &s1,const string &s2,Func);
  • 这两个语句声明的是同一个函数,在第一句中,编译器自动的将Func表示的函数类型转化为指针

返回指向函数的指针

  • 和数组类似,不能返回一个函数,但是可以返回一个指向函数的类型的指针。
  • 必须将返回的类型写成指针的形式,编译器不会自动的将函数的返回类型当成对应的指针类型进行处理。
  • 要想声明一个返回函数指针的函数,最简单的方法是使用类型别名
    using F = int(int*,int); //F是函数类型,不是指针
    using PF = int(*)(int *,int);//PF是指针类型
  • 和函数的形参一样,返回的类型不会自动地转化成指针。必须显示将返回类型指定为指针。
PF f1(int); //正确,PF是指向函数的指针,f1返回指向函数的指针
F f1(int);  //错误,F是函数的类型,f1不可以返回一个函数
F *f1(int); //正确,显示的指定返回的类型是指向函数的指针
  • 也可以直接使用下面的形式直接声明f1   int(*f1(int))(int *,int);
  • 按照由内达外的形式阅读这条语句,f1有形参列表,所以f1是一个函数;f1前面有*,所以f1返回的是一个指针,指针的类型本身也包含了形参的列表,因此指针指向函数,该函数的返回类型是int。
  • 还可以使用尾置返回的类型的方式来声明一个返回函数指针的函数 auto f1(int) -> int (*)(int *,int);

将auto和decltype用于函数指针类型

  • 如果明确知道返回的函数是哪一个,就可以使用decltype简化书写函数指针返回类型的过程。
  • 假定有两个函数,返回的类型都是string::size_type,并且各有两个const string&类型的形参,编写第三个函数,接收一个string类型的参数,返回一个指针,这个指针指向前两个函数中的一个。
    string::size_type sumLength(const string &,const string &);
    string::size_type largerLength(const string &,const string &);
    //根据形参的取值,编写的getFcn函数返回指向上面函数的其中一个
    decltype(sumLength) * getFcn(const string &);
  • 声明getFcn唯一需要注意的地方是,牢记将decltype函数作用于某一个函数的时候,返回的是函数的类型而不是指针类型。因此,只有显示地加上 * 表示需要返回的是指针,而不是函数的本身。

猜你喜欢

转载自blog.csdn.net/CHYabc123456hh/article/details/109028133