一个难于理解的C++函数指针问题

2014-01-15 01:18王玉山
山东工业技术 2014年20期
关键词:常量指针指向

王玉山

(广东外语外贸大学,广州 510440)

一个难于理解的C++函数指针问题

王玉山

(广东外语外贸大学,广州 510440)

摘要:指针是C、C++程序设计语言中一个比较复杂、难于掌握的概念。但又是任何一个C、C++程序设计者必须过的一道门槛。本文只就其中比较难难于理解的函数指针的一个例子加以阐述。希望对于C、C++程序设初学者有所帮助。

关键词:C++程序设计;C++函数指针;

1 什么是指针

指针常量与指针变量统称为指针。有关变量(类对象)、数组、函数、字符串常量的地址值都是地址常量,它们不能被赋值,只能做右值;可以被赋值的地址变量是指针变量,它们可以做左值也可以作右值。

2 函数指针

函数名是函数代码段的入口地址,是地址常量,只能做右值;指向函数的指针变量是用来存放函数的入口地址的,可以做左值也可以做右值。

3 函数指针变量的类型与赋值的要求

象普通变量赋值一样,函数指针变量的赋值要求右值和左值必须类型一致。什么是函数指针的类型呢?就是在定义函数指针时,我们把指针名去掉,剩下的部分就是函数指针的类型。

4 一个难于理解的函数指针的例子

int (*return_fun(char op))(int, int){……}。去掉return_fun(char op)后留下部分为:int (*)(int, int),即为函数return_fun(char op)返回的类型,是一个返回值为整形,有2个整形参数的函数。它的形参是字符变量char op。

#include <iostream>

using namespace std;

int add(int a, int b)

{

return a + b;}

int sub(int a,int b)

{

return a-b;

}

int mul(int a, int b)

{

return a * b;

}

int div(int a, int b)

{

return b?a/b:-1;

}

下面定义的return_fun(char op),即为返回指向函数的指针函数,该函数参数是char op。

int (*return_fun(char op))(int, int)

{

switch (op)

{

case '+':return add;//返回函数的地址,即函数名。

case '-':return sub;

case '*':return mul;

case '/':return div;

default:

return NULL;

}

}

//s_fp为指向函数的指针变量,指向有2个整形参数,返回值为整形的函数。 这里指向函数的指针变量 s_fp的右值是:return_ fun(op),return_fun(op)是一个函数调用、返回一个函数指针常量,即四个函数名add、sub、mul、div之一。

//下面的语句根据上一步得到的函数的地址调用相应函数,并返回运算结果。

if (s_fp)return s_fp(a, b);

else return -1;

}

int main(int argc, char** argv){

int a = 800, b = 200;

cout<<a<<"+"<<b<<"="<<calc(a,'+', b )<<endl;

cout<<a<<"-"<<b<<"="<<calc(a, '-', b)<<endl;

cout<<a<<"*"<<b<<"="<<calc(a, '*',b)<<endl;

cout<<a<<"/"<<b<<"="<<calc(a,'/', b )<<endl;

return 0;

}

以上程序在DevC++5.4.2版本下通过试验。

5 函数指针需要注意的几个问题

指向函数的指针,定义的时候为了保证类型一致,少犯错误。可以把函数定义的头部搬到定义的地方,在后面加上分号,把原来的函数名换为合法的标示符。如有函数:int add(int a, int b){return a + b;}。我们就把这个函数头部的函数名用Psum代替、省掉参数名、将标示符左侧加*号,必须将*号与标示符加括号进行绑定得到:int (* Psum )(int , int);此时Psum就是可以指向int add(int a, int b){return a + b;}函数的指针变量了。注意这个用于绑定的括号绝对不能省掉,如果省掉Psum就不是变量了!成了这样:int * Psum (int , int);这就成了返回整形指针的函数原形声明了。Psum也成了常量。

象普通变量一样,指向函数的指针变量也必须先定义后使用。

前面函数头部为:int (*return_fun(char op))(int, int)的例子中,是一个比较复杂的应用,该代码段定义的函数为return_fun(char op),而函数return_fun(char op))的返回类型是int (*return_fun(char op))(int,int)中把return_fun(char op)去掉后留下的部分:int (*)(int, int),这是一个指向函数的指针类型。在本例中最右侧的括号(int, int)是绝对不能省掉的,因为它是确定return_fun(char op)返回类型的关键。

再看以下代码段:void (*setF1(void (*f)()))(){……}。我们该如何理解?当然要从setF1为起点,右边的括号有几个,这看起来让人有点头晕。这里要特别注意圆括号的运算级别和结合性,我们知道圆括号的优先级是1级,左结合性。而这里的*号是间接访问运算符,优先级是1级。所以应该先有setF1(void (*f)()),它是一个整体,setF1()的参数是void (*f)(),是一个指向函数的指针参数,在void (*setF1(void (*f)()))()中,把setF1(void (*f)())去掉后留下的部分是void (*)()就是函数setF1的返回类型。

参考文献:

[1]王珊珊等著.C++程序设计教程(第2版),北京:机械工业出版社,2011年1月第 2 版,ISBN978-7-111-33022-6.

[2]谭浩强著.C程序设计,第三版,北京, 清华大学出版社,2005年 7月第3 版,ISBN 7-302-10853- 6/TP·7217.

[3]史上最牛逼的 C++指针 http://wenku.baidu.com/link?url=Mw5lETdR_tZo2-6zbkNmj7pZPb7OiiYPzwrvO0epmv6SAX14UFJ Yq9u3xt5gPwOlM8u1ZKlscq2U-SfUk6GshQooN59vaVJxJAo8YxLDWuy.

猜你喜欢
常量指针指向
科学照亮世界
——卡文迪什测定万有引力常量
科学备考新指向——不等式选讲篇
垂悬指针检测与防御方法*
中年级“生本写作”教学的“三个指向”
一次函数的学习引导
为什么表的指针都按照顺时针方向转动
VHDL中常用的数据对象
浅析C语言指针
解决常量与变量问题的四种策略