【C】——C利用回调函数实现多态
案例:
功能:可以根据用户输入的命令完成相应的功能;
例如: 用户输入 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利用回调函数实现多态的更多相关文章
- Unity 之 C# 利用回调函数实现C++匿名函数
做C++开发的都用过匿名函数很好用,可是C#开发怎么实现呢?前几天做一个拍照功能的时候.我偶然发现某个函数假设是C++的话.用匿名函数太好了,于是開始研究C#的回调,代理.托付等,最后总算是实现了我想 ...
- jQuery回调函数
1.引言 今天在学习<jQuery基础教程>在学习编写插件的时候,书中说利用回调函数来当参数,会极大的提高程序的灵活性.对回调函数很陌生.研究了一下给的示例程序.感觉对回调函数有了基本的了 ...
- jquery回调函数的一个案例
1.引言 今天在学习<jQuery基础教程>在学习编写插件的时候,书中说利用回调函数来当参数,会极大的提高程序的灵活性.对回调函数很陌生.研究了一下给的示例程序.感觉对回调函数有了基本的了 ...
- JS 对于回调函数的理解,和常见的使用场景应用,使用注意点
很经常我们会遇到这样一种情况: 例如,你需要和其他人合作,别人提供数据,而你不需要关注别人获取或者构建数据的方式方法. 你只要对这个拿到的数据进行操作. 这样,就相当于我们提供一个外在的函数,别人 ...
- c++语言虚函数实现多态的原理(更新版)
自上一个帖子之间跳过了一篇总结性的帖子,之后再发,今天主要研究了c++语言当中虚函数对多态的实现,感叹于c++设计者的精妙绝伦 c++中虚函数表的作用主要是实现了多态的机制.首先先解释一下多态的概念, ...
- Promise对象和回调函数,解决异步数据传递问题
下面的代码例子,均已小程序的异步请求数据为案例来说明 1.利用回调函数,来解决异步数据传递问题 异步操作api.js const getBooks = (url, callback) => { ...
- js中回调函数,promise 以及 async/await 的对比用法 对比!!!
在编程项目中,我们常需要用到回调的做法来实现部分功能,那么在js中我们有哪些方法来实现回调的? 方法1:回调函数 首先要定义这个函数,然后才能利用回调函数来调用! login: function (f ...
- [JS]回调函数和回调地狱
回调函数 小明在奶茶店点了奶茶,店员开始制作奶茶,此时"制作奶茶"与"小明等待奶茶"是一个同时进行的不同的两个事件(任务),那么,小明获取店员制作成功的奶茶是从 ...
- 利用闭包向post回调函数传参数
最近在闲逛XX站的时候,打算搞个破坏,试试有多少人还是用初始密码登陆.比较懒,所以直接打开控制台来写. 所以问题可以描述为: 向后端不断的post数据,id从1~5000自增,后端会根据情况来返回值r ...
随机推荐
- PHP断点调试工具Xdebug的安装
Xdebug是一个PHP程序调试器,可以用来跟踪,调试和分析PHP程序的运行状况.其实调试PHP还有其他工具比如Zend Debugger,但zend官方不是免费发布的,后来更新为zend Serve ...
- Android 消息分发机制
Android 中针对耗时的操作,放在主线程操作,轻者会造成 UI 卡顿,重则会直接无响应,造成 Force Close.同时在 Android 3.0 以后,禁止在主线程进行网络请求. 针对耗时或者 ...
- 四、s3c2440 裸机开发 通用异步收发器UARN
四.通用异步收发器UARN 原文地址 http://blog.csdn.net/woshidahuaidan2011/article/details/51137047 by jaosn Email: ...
- HDU 1431 素数回文
有人问我这个问题. 个人感觉暴搜会TLE O(n*sqrt(n)).n=100000000:(推断素数用2~sqrt(n)+1 去除) 还是枚举好了. 枚举 1~10000,把他每一位存下来,回文数已 ...
- 基于PHPExcel常用方法总结(phpexcel类库实例)
分享下对PHPExcel的常用方法进行详细的总结与分析. 对phpexcel类库不熟悉的朋友,可以阅读下<phpexcel中文帮助手册>中的内容,具体实例大家可以phpexcel快速开发指 ...
- iOS 画平滑曲线的方法及取音频数据的方法
源码:http://files.cnblogs.com/ios8/iOS%E5%BF%83%E7%94%B5%E5%9B%BEDemo.zip 取音频数据和画波形图的方法 ViewController ...
- lua -- handler
handler 将 Lua 对象及其方法包装为一个匿名函数. 格式: 函数 = handler(对象, 对象.方法) 在 quick-cocos2d-x 中,许多功能需要传入一个 Lua 函数做参数, ...
- .NET 获得指定XML配置文件内容
/// <summary> /// 获得指定XML文件内容 /// </summary> /// <param name="strPath">X ...
- Android,XML解析
XML解析三种方式 DOM 通用性强,它会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树.检索所需的数据: 简单直观,但需要将文档读取到内存,并不太适合移动设备: SAX ...
- 【消息】linux之消息队列
1.机制 消息队列的运行方式与命名管道非常相似. 欲与其他进程通信的进程只需要将消息发送到消息队列中,目的进程就从消息队列中读取需要的消息. 2.源码 1)发送方 //msg_send.c #in ...