zoukankan      html  css  js  c++  java
  • 【C】——C利用回调函数实现多态

    案例:

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

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

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

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

     1 //回调函数的用处
     2 #include <stdio.h>
     3 #include <string.h>
     4 
     5 void hello(void);
     6 int my_strcmp(char* des, char* src);
     7 void hi(void);
     8 
     9 int main(void){
    10     char val[20] = {}; 
    11     while(1){
    12         gets(val);    
    13         if(!my_strcmp(val,"hello")){
    14             hello();
    15         }   
    16         else if(!my_strcmp(val,"exit")){
    17             break;
    18         }   
    19         else if(!my_strcmp(val,"hi")){
    20             hi();
    21         }   
    22     }   
    23     return 0;
    24 }
    25 void hello(void){
    26     printf("hello
    ");
    27 }
    28 void hi(void){
    29     printf("hi
    ");
    30 }
    31 
    32 //字符串比较函数
    33 int my_strcmp(char* des, char* src){
    34     while(*des){
    35         if(*des != *src)
    36             return 1;
    37         des++;
    38         src++;
    39     }
    40     return *src - *des;
    41 }

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

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

    第二种方案:

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

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

      然后定义一个命令数组:

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

      跟命令相对应的函数为:

     1 static void cmd_hello(void){
     2     hello();
     3 }
     4 
     5 static void cmd_hi(void){
     6     hi();
     7 }
     8 
     9 static void cmd_exit(void){
    10     exit(0);
    11 }

    相对应的功能函数为:

    1 void hello(void){
    2     printf("hello
    ");
    3 }
    4 void hi(void){
    5     printf("hi
    ");
    6 }

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

    1 cmd_t* my_find(const char* val){
    2     int i;
    3     for(i = 0; i < sizeof(cmd_tbl)/sizeof(cmd_tbl[0]); i++){
    4         if(!my_strcmp(val,cmd_tbl[i].name)){
    5             return &cmd_tbl[i];
    6         }
    7     }
    8     return 0;
    9 }

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

    main 函数如下:

     1 int main(void){
     2     char val[20] = {};
     3     cmd_t *cmd_ptr;
     4     while(1){
     5         gets(val);
     6         cmd_ptr = my_find(val);
     7         if(cmd_ptr){
     8             cmd_ptr->func();
     9         }
    10         else{
    11             printf("no cmd
    ");
    12         }
    13     }
    14     return 0;
    15 }

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

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

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

  • 相关阅读:
    GitLab用户权限管理
    类似vant中的tab实现
    Gitgitee/github/gitlab账号分离
    Vim操作
    partition by 用法
    crontab执行feat_gen.sh时,报错找不到pyspark
    SQL同一个字段出现null和0值,有何区别,原因是什么?left join导致null值出现,case when导致0值出现
    linux 定时任务crontab的用法
    卡方检验
    ROC与AUC
  • 原文地址:https://www.cnblogs.com/ngnetboy/p/3622160.html
Copyright © 2011-2022 走看看