函数指针 C/C++

指向函数的指针
函数指针是指指向函数而非指向对象的指针。像其他指针一样,函数指针也
指向某个特定的类型。函数类型由其返回类型以及形参表确定, 而与函数名无关:
// pf points to function returning bool that takes two const string
references
bool (*pf)(const string &, const string &);
这个语句将 pf 声明为指向函数的指针,它所指向的函数带有两个 const
string& 类型的形参和 bool 类型的返回值。

371
*pf 两侧的圆括号是必需的:
// declares a function named pf that returns a bool*
bool *pf(const string &, const string &);
typedef 简化函数指针的定义
函数指针类型相当地冗长。使用 typedef 为指针类型定义同义词,可将函
数指针的使用大大简化:(第 2.6 节):
typedef bool (*cmpFcn)(const string &, const string &);
该定义表示 cmpFcn 是一种指向函数的指针类型的名字。该指针类型为“指
向返回 bool 类型并带有两个 const string 引用形参的函数的指针”。在要使
用这种函数指针类型时,只需直接使用 cmpFcn 即可,不必每次都把整个类型声
明全部写出来。
指向函数的指针的初始化和赋值
在引用函数名但又没有调用该函数时,函数名将被自动解释为指向函数的指
针。假设有函数:
// compares lengths of two strings
bool lengthCompare(const string &, const string &);
除了用作函数调用的左操作数以外,对 lengthCompare 的任何使用都被解
释为如下类型的指针:
bool (*)(const string &, const string &);
可使用函数名对函数指针做初始化或赋值:
cmpFcn pf1 = 0; // ok: unbound pointer to function
cmpFcn pf2 = lengthCompare; // ok: pointer type matches function's
type
pf1 = lengthCompare; // ok: pointer type matches function's
type
pf2 = pf1; // ok: pointer types match

372
此时,直接引用函数名等效于在函数名上应用取地址操作符:
cmpFcn pf1 = lengthCompare;
cmpFcn pf2 = &lengthCompare;
函数指针只能通过同类型的函数或函数指针或 0 值常量表达
式进行初始化或赋值。
将函数指针初始化为 0,表示该指针不指向任何函数。
指向不同函数类型的指针之间不存在转换:
string::size_type sumLength(const string&, const string&);
bool cstringCompare(char*, char*);
// pointer to function returning bool taking two const string&
cmpFcn pf;
pf = sumLength; // error: return type differs
pf = cstringCompare; // error: parameter types differ
pf = lengthCompare; // ok: function and pointer types match exactly
通过指针调用函数
指向函数的指针可用于调用它所指向的函数。可以不需要使用解引用操作
符,直接通过指针调用函数:
cmpFcn pf = lengthCompare;
lengthCompare("hi", "bye"); // direct call
pf("hi", "bye"); // equivalent call: pf1 implicitly
dereferenced
(*pf)("hi", "bye"); // equivalent call: pf1 explicitly
dereferenced
如果指向函数的指针没有初始化,或者具有 0 值,则该指针不
能在函数调用中使用。只有当指针已经初始化,或被赋值为指
向某个函数,方能安全地用来调用函数。
函数指针形参
函数的形参可以是指向函数的指针。这种形参可以用以下两种形式编写:
373
[View full width]
/* useBigger function's third parameter is a pointer to function
* that function returns a bool and takes two const string references
* two ways to specify that parameter:
*/
// third parameter is a function type and is automatically treated
as a pointer to
function
void useBigger(const string &, const string &,
bool(const string &, const string &));
// equivalent declaration: explicitly define the parameter as a
pointer to function
void useBigger(const string &, const string &,
bool (*)(const string &, const string &));
返回指向函数的指针
函数可以返回指向函数的指针,但是,正确写出这种返回类型相当不容易:
// ff is a function taking an int and returning a function pointer
// the function pointed to returns an int and takes an int* and an
int
int (*ff(int))(int*, int);
阅读函数指针声明的最佳方法是从声明的名字开始由里而
外理解。
要理解该声明的含义,首先观察:
ff(int)
将 ff 声明为一个函数,它带有一个 int 型的形参。该函数返回
int (*)(int*, int);
它是一个指向函数的指针,所指向的函数返回 int 型并带有两个分别是
int* 型和 int 型的形参。
使用 typedef 可使该定义更简明易懂:
// PF is a pointer to a function returning an int, taking an int*
and an int
typedef int (*PF)(int*, int);

374
PF ff(int); // ff returns a pointer to function
允许将形参定义为函数类型,但函数的返回类型则必须是指向
函数的指针,而不能是函数。
具有函数类型的形参所对应的实参将被自动转换为指向相应函数类型的指
针。但是,当返回的是函数时,同样的转换操作则无法实现:
// func is a function type, not a pointer to function!
typedef int func(int*, int);
void f1(func); // ok: f1 has a parameter of function type
func f2(int); // error: f2 has a return type of function type
func *f3(int); // ok: f3 returns a pointer to function type
指向重载函数的指针
C++ 语言允许使用函数指针指向重载的函数:
extern void ff(vector<double>);
extern void ff(unsigned int);
// which function does pf1 refer to?
void (*pf1)(unsigned int) = &ff; // ff(unsigned)
指针的类型必须与重载函数的一个版本精确匹配。如果没有精确匹配的函
数,则对该指针的初始化或赋值都将导致编译错误:
// error: no match: invalid parameter list
void (*pf2)(int) = &ff;
// error: no match: invalid return type
double (*pf3)(vector<double>);
pf3 = &ff;
小结
函数是有名字的计算单元,对程序(就算是小程序)的结构化至关重要。函
数的定义由返回类型、函数名、形参表(可能为空)以及函数体组成。函数体是
调用函数时执行的语句块。在调用函数时,传递给函数的实参必须与相应的形参
类型兼容。
给函数传递实参遵循变量初始化的规则。非引用类型的形参以相应实参的副
本初始化。对(非引用)形参的任何修改仅作用于局部副本,并不影响实参本身。

375
复制庞大而复杂的值有昂贵的开销。为了避免传递副本的开销,可将形参指
定为引用类型。对引用形参的任何修改会直接影响实参本身。应将不需要修改相
应实参的引用形参定义为 const 引用。
在 C++ 中,函数可以重载。只要函数中形参的个数或类型不同,则同一个
函数名可用于定义不同的函数。编译器将根据函数调用时的实参确定调用哪一个
函数。在重载函数集合中选择适合的函数的过程称为函数匹配。
C++ 提供了两种特殊的函数:内联函数和成员函数。将函数指定为内联是建
议编译器在调用点直接把函数代码展开。内联函数避免了调用函数的代价。成员
函数则是身为类成员的函数。本章介绍了简单的成员函数,在第十二章将会更详
细地介绍成员函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值