例子三,函数框架和程序指针(4)

 

你想吃一个苹果,是从果农那儿买呢,还是到超市买,本文带你走入函数指针的精彩世界。...



学习一个新的概念时,我特别喜欢“概念学习法”,一般分为几步:
1. 明白是什么;
2. 同其他概念的关联关系,相似及差异之处;
3. 为何会产生这个概念,用来解决什么问题。

概念学习法为何学习效果好呢,实际上这要从人脑学习知识的特点来分析。人脑擅长关联分析思考,但不擅长记忆,尤其是不擅长记忆大量的知识细节,只有持续的强化才能记住,而且一段时间不用就忘记了。

以函数指针这个概念为例,先要理解其概念,明白它首先依然是一个指针,但因为程序也是数据(冯诺依曼结构),因此指针可以指向程序。

第二步我们来分析它同其他指针的关联关系,他们之间有差异,如表示方式同常规指针差异很大,有关联,依然遵从指针变量的运算法则。

而第三步,我们要思考为何会产生了这个东东呢,一定是需求推动的吧,但是什么需求推动的呢。带着这个问题去思考函数指针,会发现另一番天空,这是概念学习法的关键所在。

假如很长一段时间,我们都没有用到函数指针,脑袋中关于函数指针的细节基本都忘记了,但我们当初的深入分析是不会忘记的, 一旦碰到类似的需求,会自然而然的想起函数指针。很多细节忘记了,快速回忆学习一下即可,而且随着不断的使用,甚至那些细节也会成为你生命的一部分,甚至已经成为下意识动作,想忘记已不可能了。

很遗憾的是,从小到大我们接触的教育,反复学习强化的都是细节知识,一边学一边忘,到头来,空悲切。

◇◇◇

今天,就让我们来分析一下函数指针能做什么。

如果我们要使用一个功能,是直接调用呢,还是间接调用呢,很多人肯定会回答直接调用。但如果关联思考一个问题,如果我们现在想吃苹果了,是直接找果农买苹果呢,还是到超市去买。

在计算机行业内有一句经典名言,任何问题都可以通过增加一层抽象层来实现,而函数指针经常就是用来实现抽象的,它让程序的世界变得精彩纷呈。

我们来举几个简单的例子,给大家展现这种抽象的概念。

◇◇◇

还记得例子二吗,是一个学生信息管理系统,侧重于加强对指针和链表的理解。如果现在有这样的一个需求,每个学生需要增加一个自我介绍环节,为了爱惜每个学生的表现欲,形式不限,可以是一段话,可以是一个动画,甚至可以是一个游戏。

这儿大家不妨暂停一会儿,头脑风暴一下,思考从程序的角度,如何组织“自我介绍”这个数据模型呢。

……

我们没有数据类型来存储“自我介绍”这个数据了,不妨将其下方给每个学生,如何下方呢,呵呵,自然是通过函数指针来实现。

经过这样的改造,我们的学生信息结构如下:

typedef void (*SelfIntro)(void);
struct student
{
int num;        /* 学号 */
float score;    /* 成绩 */
SelfIntro pfnSelf;      /* 自我介绍 */
struct student *next; /* 指向下一结点 */
};

每个学生可以有个性的自我介绍,示例如下:

void student1()
{
printf("我是小马儿,一个渴望良知与灵魂的工程师。");
}
void student2()
{
/* 准备开始播放一段动画 */
play(...);
}
void student3()
{
/* 准备开始唱歌 */
music(...);
}
……

然后,在构建学生信息时,需要将这个各具特性的函数传递进去,构建学生信息的函数原型如下:
void createStudent(int num, float score, SelfIntro pfnSelf);

构建过程如下:
createStudent(1, 35, student1);
createStudent(2, 96, student2);
createStudent(3, 89, student3);
……

此时,奇妙的事情发生了,虽然每个学生的个人介绍千差万别,但学生信息管理系统可以以统一的方式组织,如让所有考试及格的学生依次做一个自我介绍,程序示意如下:

void fun(void)
{
student* p;
for (p = mgr.next; p != NULL; p = p->next)
{
if (p->score >= 60.0f)
p->pfnSelf();
}
}

◇◇◇

知识学习的关键在于举三反一,大家不妨在自己的产品代码中几个类似这儿策略的代码例子,如果上心,会惊奇的发现优秀的程序几乎总是在重复这些简单的技巧,欢迎再留言区留言。

下篇文章我们会继续举例,一起带大家走入函数指针的精彩世界,期望你的光临。

我是小马儿,一个渴望良知与灵魂的工程师,欢迎您的陪伴与同行。


    关注 和小马儿一起蹚C语言


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册