您的位置:首页 > 编程语言 > C语言/C++

c++中的函数指针

2021-07-23 22:44 936 查看

引言

函数指针指向的是函数而不是对象。函数指针指向某种特定类型,就像我们可以定义指向int变量的指针,指向char变量的指针以及指向string变量的指针,函数指针指向的这种特定类型由函数的返回类型形参类型共同决定,而与函数名无关。

例如有一个函数

compare
声明如下:

bool compare(const string &, const string &);

若要定义指向该函数的指针,那么应该像这样:

bool (*pf)(const string &,const string &);

依然遵循由内而外的原则阅读声明:

  • 首先
    (*pf)
    表明变量
    pf
    是指针类型;
  • 而后面的
    (const string &,const string &)
    是形参列表,表明指针
    pf
    指向一个函数,该函数的形参列表如上;
  • 最后,最左边的
    bool
    表明这个函数的返回类型是
    bool

Note:

bool *pf(const string &,const string &);

对比上面的这个声明和上上个声明,差别在

(*pf)
*pf
上。
(*pf)
指明
pf
是指针类型,而
*pf
对应的那条声明指明
pf
是个函数,函数的返回类型是
bool *
。因此,声明指向函数的指针时,
(*pf)
两端的括号必不可少,至于差别大家也看到了。

使用函数指针

当我们把函数名作为一个值使用时,该函数自动转换成指针。 例如对上面的

compare
函数和函数指针
pf
,若要使
pf
指向
compare
函数,我们有:

pf = compare;  //函数名自动转换为指针
pf = &compare; //等价的赋值,&可选。

pf = 0;  //表明pf不指向任何函数
pf = nullptr;   //与上句等价

并且,我们能够直接使用指向函数的指针调用该函数,不一定非要解引用指针。例如:

bool b1 = pf("你好", "Fuck!");  //直接使用指向函数的指针调用函数
bool b2 = (*pf)("你好", "Fuck!"); //等价的调用。先解引用指针,再调用函数。
bool b2 = *pf("你好", "Fuck!"); //错误的调用。函数调用运算符()的优先级高于解引用运算符*的优先级。
/*
bool b2 = *pf("你好", "Fuck!");//等价于以下两条语句:

bool tmp = pf("你好", "Fuck!"); //即调用pf指向的函数。
bool b2 = *tmp; //对tmp解引用。显然错误,因为不能对bool类型解引用
//如果compare函数返回char *类型,则语句bool b2 = *pf("你好", "Fuck!");反而正确
*/
bool b3 = compare("你好", "Fuck!"); ////等价的调用。直接使用函数。

我们再来加深下对函数指针指向的类型的理解: 假设有三个函数声明如下:

bool compare1(const string &, const string &);
bool compare2(const string &, const string &);
bool compare3(const int &, const int &);

函数指针

pf
如下:

bool (*pf) (const string &, const string &);
pf = compare1;  //正确
pf = compare2;  //正确
pf = compare3;  //错误,形参不匹配

(重载函数)的指针

考虑重载的函数:

void f(int *);
void f(int);

void (*pf) (int) = f; //pf指向void f(int);

编译器通过指针类型决定指向哪个重载函数,指针类型必须与重载函数中的某一个精确匹配(返回类型和形参列表精确匹配)。

将函数指针作为形参

就如我们不能定义数组类型的形参一样,我们不能定义函数类型的形参,但是形参可以是指向函数的指针。形参看起来是函数类型,实际上当成指针使用。 例如:

//第三个形参是函数类型,但会自动转换为指向函数的指针。即,pf是指向函数的指针。
void f(const string &s1, const string &s2, bool pf(const string &, const string &));

//等价的声明,显式地将形参定义为指向函数的指针。
void f(const string &s1, const string &s2, bool (*pf)(const string &, const string &));

直接把函数作为实参时,会自动转换为指针。

//自动将函数compare转换为指向该函数的指针。
f("你好", "Fuck", compare);

将指向函数的指针作为返回类型

就如我们不能在函数中返回数组类型一样,我们不能直接返回函数类型,但可以返回指向函数的指针。以下声明一个返回函数指针的函数:

int (*f(int)) (int *, int);

从内而外阅读声明,首先

*f(int)
表明
f
是函数,参数是
int
,返回指针类型。
(int *, int)
表明指针指向函数一个,且参数列表为
(int *, int)
,最左边的int表明指向的该函数返回
int

亦可以使用尾置返回类型的方式:

auto f(int) -> int (*) (int*, int);

该声明与上一条声明等价。

将decltype用于函数指针类型

如果我们明确知道返回的函数是哪一个,就能使用

decltype
简化书写函数指针。

decltype(compare) *p; //p是一个指向compare函数对应类型(只是返回类型和形参,函数名不属于类型的一部分)的指针类型
decltype(compare) * f(); //函数声明,f是一个函数,没有形参,返回类型为指向compare函数对应类型(只是返回类型和形参,函数名不属于类型的一部分)的函数指针类型

Note:

decltype
作用于某个函数时,返回函数类型而不是指针类型,需要显式加上
*
表明我们需要指针类型。

声明: c++ Basic是对《C++ Primer 第五版》的个人总结与疑难解释,主要用于个人日后复习。 如果想要深入了解更多,请支持正版。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: