案例:

  功能:可以根据用户输入的命令完成相应的功能;

  例如: 用户输入  hello   完成输出 hello的功能。

        用户输入  hi   完成输出 hi 的功能。

一般的写法可能会写两个函数来实现 输出 hello 和 hi 的功能,然后在根据用户输入的字符串与 hello 和 hi 比较,然后执行相应的函数。代码如下:

 //回调函数的用处
#include <stdio.h>
#include <string.h> void hello(void);
int my_strcmp(char* des, char* src);
void hi(void); int main(void){
char val[] = {};
while(){
gets(val);
if(!my_strcmp(val,"hello")){
hello();
}
else if(!my_strcmp(val,"exit")){
break;
}
else if(!my_strcmp(val,"hi")){
hi();
}
}
return ;
}
void hello(void){
printf("hello\n");
}
void hi(void){
printf("hi\n");
} //字符串比较函数
int my_strcmp(char* des, char* src){
while(*des){
if(*des != *src)
return ;
des++;
src++;
}
return *src - *des;
}

  好像这样写也听不错的。可以完美的完成需求。但是如果当命令再增加一个,我们是不是就需要再写一个功能函数,然后再增加一个分支。如果当某天命令加到上百个的时候我们是不是也要在 main 函数中开一百个分支来完成判断???

  额,对于一个程序员来讲,这可能是一个 bad idea!我们是不是可以只写一个函数就可以完成主函数的功能呢?答案是肯定的。

第二种方案:

  首先我们需要一个数组来把所有的命令全部存放到里面,只是需要的时候我们再从数组里面找,然后把相应的命令与功能绑定到一起。因此我们可以定义一个结构体,里面存放一个 cmd 命令 和 一个cmd 命令相对应的功能函数,而这个函数应该为一个函数指针,当我们使用此函数的时候,让系统自己调用此函数。

 //定义一个函数指针
typedef void (*callback)(void);
//定义命令结构体
typedef struct cmd{
char name[]; //命令的名字
callback func; //与命令相对应的函数指针
}cmd_t;

  然后定义一个命令数组:

 //声明命令数组
const cmd_t cmd_tbl[] = {
{"hello",cmd_hello},
{"hi",cmd_hi},
{"exit",cmd_exit},
};

  跟命令相对应的函数为:

 static void cmd_hello(void){
hello();
} static void cmd_hi(void){
hi();
} static void cmd_exit(void){
exit();
}

相对应的功能函数为:

 void hello(void){
printf("hello\n");
}
void hi(void){
printf("hi\n");
}

此时我们还需要一个查找命令函数:

 cmd_t* my_find(const char* val){
int i;
for(i = ; i < sizeof(cmd_tbl)/sizeof(cmd_tbl[]); i++){
if(!my_strcmp(val,cmd_tbl[i].name)){
return &cmd_tbl[i];
}
}
return ;
}

此函数返回的是一个结构体指针,若没有找到命令则返回0;

main 函数如下:

 int main(void){
char val[] = {};
cmd_t *cmd_ptr;
while(){
gets(val);
cmd_ptr = my_find(val);
if(cmd_ptr){
cmd_ptr->func();
}
else{
printf("no cmd\n");
}
}
return ;
}

  此时的代码的可读性就变得很高了,如果想添加另一条命令的时候,main 函数根本不用动,只需要在命令数组中添加数组,然后添加一个命令相对应的功能函数就可以了。 自己写的函数不需要自己调用,而是根据用户所输入的信息调用相应的函数,以上结构体的函数成为回调函数。正是因为回调函数的存在让C语言实现了多态的功能。

  多态:基类的同一调用,在不同的子类上有不同的表现。通俗一点讲就是:根据不同的类型实现不同的功能。

  而此时,我们无需关心用户的输入的是什么。就可以完成相应的功能。

【C】——C利用回调函数实现多态的更多相关文章

  1. Unity 之 C# 利用回调函数实现C++匿名函数

    做C++开发的都用过匿名函数很好用,可是C#开发怎么实现呢?前几天做一个拍照功能的时候.我偶然发现某个函数假设是C++的话.用匿名函数太好了,于是開始研究C#的回调,代理.托付等,最后总算是实现了我想 ...

  2. jQuery回调函数

    1.引言 今天在学习<jQuery基础教程>在学习编写插件的时候,书中说利用回调函数来当参数,会极大的提高程序的灵活性.对回调函数很陌生.研究了一下给的示例程序.感觉对回调函数有了基本的了 ...

  3. jquery回调函数的一个案例

    1.引言 今天在学习<jQuery基础教程>在学习编写插件的时候,书中说利用回调函数来当参数,会极大的提高程序的灵活性.对回调函数很陌生.研究了一下给的示例程序.感觉对回调函数有了基本的了 ...

  4. JS 对于回调函数的理解,和常见的使用场景应用,使用注意点

      很经常我们会遇到这样一种情况: 例如,你需要和其他人合作,别人提供数据,而你不需要关注别人获取或者构建数据的方式方法. 你只要对这个拿到的数据进行操作. 这样,就相当于我们提供一个外在的函数,别人 ...

  5. c++语言虚函数实现多态的原理(更新版)

    自上一个帖子之间跳过了一篇总结性的帖子,之后再发,今天主要研究了c++语言当中虚函数对多态的实现,感叹于c++设计者的精妙绝伦 c++中虚函数表的作用主要是实现了多态的机制.首先先解释一下多态的概念, ...

  6. Promise对象和回调函数,解决异步数据传递问题

    下面的代码例子,均已小程序的异步请求数据为案例来说明 1.利用回调函数,来解决异步数据传递问题 异步操作api.js const getBooks = (url, callback) => { ...

  7. js中回调函数,promise 以及 async/await 的对比用法 对比!!!

    在编程项目中,我们常需要用到回调的做法来实现部分功能,那么在js中我们有哪些方法来实现回调的? 方法1:回调函数 首先要定义这个函数,然后才能利用回调函数来调用! login: function (f ...

  8. [JS]回调函数和回调地狱

    回调函数 小明在奶茶店点了奶茶,店员开始制作奶茶,此时"制作奶茶"与"小明等待奶茶"是一个同时进行的不同的两个事件(任务),那么,小明获取店员制作成功的奶茶是从 ...

  9. 利用闭包向post回调函数传参数

    最近在闲逛XX站的时候,打算搞个破坏,试试有多少人还是用初始密码登陆.比较懒,所以直接打开控制台来写. 所以问题可以描述为: 向后端不断的post数据,id从1~5000自增,后端会根据情况来返回值r ...

随机推荐

  1. javascript 20个正则表达式

    正则表达式,一个十分古老而又强大的文本处理工具,仅仅用一段非常简短的表达式语句,便能够快速实现一个非常复杂的业务逻辑.熟练地掌握正则表达式的话,能够使你的开发效率得到极大的提升. 正则表达式经常被用于 ...

  2. SSO单点登录的发展由来以及实现原理

    单点登录以及权限,在很早之前都有写过,不过都比较简单,今天就具体说一下,以及下一步要做的 1.web单系统应用 早期我们开发web应用都是所有的包放在一起打成一个war包放入tomcat容器来运行的, ...

  3. sql server中根据地图经纬度算距离

    从别的地方烤过来的,自己试了一下,可以计算 出来,不过正确不正确的就不太懂了. USE [niaoren]GO/****** Object:  UserDefinedFunction [dbo].[f ...

  4. J2EE--Servlet生命周期与原理

    Servlet是在server上执行的小程序.而在java中应用程序多是在容器中进行生命周期的管理(这里指Tomact容器). Servlet主要的架构图 首先是 web页面通过提交表单 tomact ...

  5. pyenv管理多python版本

    手动安装 cd ~ git clone git://github.com/yyuu/pyenv.git .pyenv echo 'export PYENV_ROOT="$HOME/.pyen ...

  6. HTML杂记

    1.URL  uniform resource locator 遵循格式: scheme://host.domain:port/path/filename scheme - 定义因特网服务的类型.最常 ...

  7. BD

    销售圣经:终极销售资源(销售必读,行业经典) 销售圣经2:销售之神的21.5条销售法则 Heart and Sell: 10 Universal Truths Every Salesperson Ne ...

  8. Market Guide for AIOps Platforms

    AIOps platforms enhance IT operations through greater insights by combining big data, machine learni ...

  9. matlab M文件分析工具使用(Code Analyzer and Profiler)

    Code Analyzer and Profiler Matlab中,对写在m文件(.m文件)里的代码有分析的工具,可以进行优化,这里做一个简单的介绍. Code Analyzer Code Anal ...

  10. jqgrid传入的json数据,赋值了但是没有在表格上显示

    1.  datatype: "local",属性加入这个 2. dataValue就是json对象 for (var i = 0; i <= dataValue.length ...