• 【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语言实现了多态的功能。

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

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

  • 相关阅读:
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 344 反转字符串
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
  • 原文地址:https://www.cnblogs.com/ngnetboy/p/3622160.html
Copyright © 2020-2023  润新知