函数类型和函数指针类型(摘自 linux c编程一站式学习)

 

下面再举几个例子区分函数类型和函数指针类型。首先定义函数类型F:
typedef int F(void);
这种类型的函数不带参数,返回值是int 。那么可以这样声明f和g:
F f, g;

相当于声明:
int f(void);
int g(void);
下面这个函数声明是错误的:


F h(void);


因为函数可以返回void 类型、标量类型、结构体、联合体,但不能返回函数类型,也不能返回数组
类型。而下面这个函数声明是正确的:


F *e(void);


函数e返回一个F *类型的函数指针。如果给e多套几层括号仍然表示同样的意思:


F *((e))(void);


但如果把*号也套在括号里就不一样了:


int (*fp)(void);


这样声明了一个函数指针,而不是声明一个函数。fp也可以这样声明:


F *fp;


通过函数指针调用函数和直接调用函数相比有什么好处呢?我们研究一个例子。回顾第 3 节 “数据
类型标志”的习题1,由于结构体中多了一个类型字段,需要重新实
现real_part 、img_part 、magnitude 、angle 这些函数,你当时是怎么实现的?大概是这样吧:

double real_part(struct complex_struct z)
{
if (z.t == RECTANGULAR)
return z.a;
else
return z.a * cos(z.b);
}


现在类型字段有两种取值,RECTANGULAR和POLAR ,每个函数都要if ... else ... ,如果类型字段
有三种取值呢?每个函数都要if ... else if ... else ,或者switch ... case ... 。这样维护代
码是不够理想的,现在我用函数指针给出一种实现:

double rect_real_part(struct complex_struct z)
{
return z.a;
}
double rect_img_part(struct complex_struct z)
{
return z.b;
}
414
double rect_magnitude(struct complex_struct z)
{
return sqrt(z.a * z.a + z.b * z.b);
}
double rect_angle(struct complex_struct z)
{
double PI = acos(-1.0);
if (z.a > 0)
return atan(z.b / z.a);
else
return atan(z.b / z.a) + PI;
}
double pol_real_part(struct complex_struct z)
{
return z.a * cos(z.b);
}
double pol_img_part(struct complex_struct z)
{
return z.a * sin(z.b);
}
double pol_magnitude(struct complex_struct z)
{
return z.a;
}
double pol_angle(struct complex_struct z)
{
return z.b;
}
double (*real_part_tbl[])(struct complex_struct) = { rect_real_part,
pol_real_part };
double (*img_part_tbl[])(struct complex_struct) = { rect_img_part,
pol_img_part };
double (*magnitude_tbl[])(struct complex_struct) = { rect_magnitude,
pol_magnitude };
double (*angle_tbl[])(struct complex_struct) = { rect_angle,
pol_angle };
#define real_part(z) real_part_tbl[z.t](z)
#define img_part(z) img_part_tbl[z.t](z)
#define magnitude(z) magnitude_tbl[z.t](z)
#define angle(z) angle_tbl[z.t](z)


当调用real_part(z)时,用类型字段z.t 做索引,从指针数组real_part_tbl 中取出相应的函数指针
来调用,也可以达到if ... else ... 的效果,但相比之下这种实现更好,每个函数都只做一件事
情,而不必用if ... else ... 兼顾好几件事情,比如rect_real_part 和pol_real_part 各做各的,
互相独立,而不必把它们的代码都耦合到一个函数中。

“低耦合,高内聚”(Low Coupling, HighCohesion)是程序设计的一条基本原则,这样可以更好地复用现有代码,使代码更容易维护。如果类型字段z.t 又多了一种取值,只需要添加一组新的函数,修改函数指针数组,原有的函数仍然可以不加改动地复用。

posted @ 2013-03-24 16:59  bigbigtree  阅读(1356)  评论(0编辑  收藏  举报