【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 ...
随机推荐
- 关系型数据库性能测试参考指标----SQL Server
注:以下指标取自SQL Server自身提供的性能计数器. [@more@] SQL Server 指标名称 指标描述 指标范围 指标单位 1.SQL Server中访问方法(Access Metho ...
- Android开发中无处不在的设计模式——动态代理模式
继续更新设计模式系列.写这个模式的主要原因是近期看到了动态代理的代码. 先来回想一下前5个模式: - Android开发中无处不在的设计模式--单例模式 - Android开发中无处不在的设计模式-- ...
- Unity投影器细节整理
抽了个空整理下投影器 一般投影器需要两张贴图,一张Cookie,一张FallOff. Unity提供Light和Multiple两种自带shader,和粒子类似. Cookie需要非alpha贴图,F ...
- 【Unity】12.4 通过网格分层选择行进路线
开发环境:Win10.Unity5.3.4.C#.VS2015 创建日期:2016-05-09 一.简介 在具体的游戏情景中,通过分层可以控制物体的行进路线,比如哪些物体只能住水面上行进,哪些物体只能 ...
- 行为类模式(七):观察者(Observer)
定义 定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新. UML 优点 观察者和被观察者之间是松耦合的,分别可以各自独立改变. Subject在发送 ...
- mongoose更新文档的时候让某个字段自增
Station.update({ _id: req.params.id }, { $set: req.body, $inc: { count: 1 } }, { multi: false }, cal ...
- ES performance
http://easyice.cn/ https://m.aliyun.com/yunqi/articles/60474 https://www.jianshu.com/c/d5c542376948 ...
- angular-1.3 之ng-model-options指令
ng-model-options是angular-1.3新出的一个指令,这篇文章就来介绍这个指令的用法. ng-model-options允许我们控制ng-model何时进行同步. 比如:1.当某个确 ...
- mybatis使用注解往postgresql数据库表insert数据[主键自增]的写法
建表SQL: DROP TABLE IF EXISTS person; CREATE TABLE person( person_id serial PRIMARY KEY NOT NULL, pers ...
- Windows下GUI编程——窗口
windows下创建一个基于GUI的窗口程序很简单,使用MFC或者Win32 API都可以实现.本文简单整理下windows API创建GUI应用程序的基本编码框架. 比较常见的窗口包括:桌面窗口.应 ...