【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 ...
随机推荐
- Maven pom.xml中的元素modules、parent、properties以及import(转)
前言 项目中用到了maven,而且用到的内容不像利用maven/eclipse搭建ssm(spring+spring mvc+mybatis)用的那么简单:maven的核心是pom.xml,那么我就它 ...
- kibana 的search 的的搜索提示挡住输入框
解决方案就是 [root@10-19-148-59 styles]# pwd /data/package/kibana/src/public/styles [root@10-19-148-59 sty ...
- Java:集合,Arrays工具类用法
1. 描述 Arrays工具类提供了针对数组(Array)的一些操作,比如排序.搜索.将数组(Array)转换列表(List)等等,都为静态(static)方法: binarySearch - 使用二 ...
- IOS 实现录音PCM转MP3格式(边录音边转码)
最近做的一个项目,项目中有个录音功能,采用的录音方法是IOS下的AVAudioRecorder.录音效果不错,但是录制的原生.pcm文件太大,每分钟大约10M左右. 找了下相关的音频压缩方法,用spe ...
- Java虚拟机(JVM)概述
JVM(Java虚拟机)是一个抽象的计算模型.就如同一台真实的机器,它有自己的指令集和执行引擎,可以在运行时操控内存区域.目的是为构建在其上运行的应用程序提供一个运行环境.JVM可以解读指令代码并与底 ...
- iOS开发-按钮的基本使用
// // ViewController.m // 05-用代码创建按钮 // // Created by vic fan on 2017/7/30. // Copyright © 2017年 ...
- 死亡之Makefile。。。
A=Nothing build: @rm -rf build/$(A)/* > /dev/null .PHONY: build 这是一个Makefile..只需要打开终端,在这个Makefile ...
- HBase最佳实践-用好你的操作系统
终于又切回HBase模式了,之前一段时间因为工作的原因了解接触了一段时间大数据生态的很多其他组件(诸如Parquet.Carbondata.Hive.SparkSQL.TPC-DS/TPC-H等),虽 ...
- Linux--多网卡的7种Bond模式【转】
转自:http://www.cnblogs.com/lcword/p/5914089.html 网卡bond是通过把多张网卡绑定为一个逻辑网卡,实现本地网卡的冗余,带宽扩容和负载均衡.在应用部署中是一 ...
- HBase操作(Shell与Java API)
版权声明:本文为博主原创文章,未经博主允许不得转载. 转: http://blog.csdn.net/u013980127/article/details/52443155 下面代码在Hado ...