【问题标题】:How pointers to function as struct member useful in C?指向作为结构成员的指针在 C 中如何有用?
【发布时间】:2012-10-19 10:10:07
【问题描述】:

我对 C 编程并不陌生。但是我不明白在 C 中保持指针作为结构成员的作用有什么用处。例如

    // Fist Way: To keep pointer to function in struct
    struct newtype{
        int a;
        char c;
        int (*f)(struct newtype*);
    } var;
    int fun(struct newtype* v){
        return v->a;
    }

    // Second way: Simple
    struct newtype2{
        int a;
        char c;
    } var2;
    int fun2(struct newtype2* v){
        return v->a;
    }

    int main(){

        // Fist: Require two steps
        var.f=fun;
        var.f(&var);

        //Second : simple to call
        fun2(&var2);    
    }

程序员是否使用它为 C 代码赋予面向对象(OO)的形状并提供抽象对象?或者让代码看起来很技术。

我认为,在上面的代码中,第二种方式更温和,也很简单。在第一种方式中,我们仍然必须通过&var,即使fun() 是结构的成员。

如果将函数指针保留在结构定义中是好的,请帮助解释原因。

【问题讨论】:

标签: c oop struct coding-style structure


【解决方案1】:

在结构上提供指向函数的指针可以让您动态选择要在结构上执行的函数。

struct newtype{
    int a;
    int b;
    char c;
    int (*f)(struct newtype*);
} var;


int fun1(struct newtype* v){
        return v->a;
    }

int fun2(struct newtype* v){
        return v->b;
    }

void usevar(struct newtype* v) {
   // at this step, you have no idea of which function will be called
   var.f(&var);
}

int main(){
        if (/* some test to define what function you want)*/) 
          var.f=fun1;
        else
          var.f=fun2;
        usevar(var);
    }

这使您能够拥有一个调用接口,但根据您的测试是否有效调用两个不同的函数。

【讨论】:

  • 这都是想不到的......在c++中称为多态(运行时或编译绑定)
【解决方案2】:

如果您尝试进行某种“基于对象”的编程,它会很有用。

如果您曾经看过 Quake 3 引擎的源代码.. 您可以清楚地看到大多数“实体”都有定义它们的属性,以及它们所做的工作 [它们是函数指针]。

分离属性和函数(通过 C 中的函数指针)定义了“结构”对象的属性和它们可以执行的操作。

例如:

struct _man{
   char name[];
   int age;
   void (*speak)(char *text);
   void (*eat)(Food *foodptr);
   void (*sleep)(int hours); 
   /*etc*/
};

void grijesh_speak(char *text)
{
   //speak;
}

void grijesh_eat(Food *food)
{
   //eat
}

void grijesh_sleep(int hours)
{
   //sleep
}

void init_struct(struct _man *man)
{
    if(man == NULL){ man = malloc(sizeof(struct _man));}
      strcpy(*man.name,"Grijesh");
      man->age = 25;
      man->speak = grijesh_speak;
      man->eat = grijesh_food;
      man->sleep = grijesh_sleep;
//etc
}

//so now in main.. i can tell you to either speak, or eat or sleep.

int main(int argc, char *argv[])
{
    struct _man grijesh;
    init_struct(&grijesh);
    grijesh.speak("Babble Dabble");
    grijesh.sleep(10);
    return 0;
}

【讨论】:

    【解决方案3】:

    我过去曾使用它在 C 中实现通用容器1

    例如:

    typedef struct generic_list_node {
      void *data;
      struct generic_list_node *next;
    } generic_list_node_t;
    
    typedef struct generic_list {
      generic_list_node_t *head;
      void *(*copy)(void *data);                 
      void (*delete)(void *data);                
      int (*compare)(void *lhs, void *rhs);      
      void (*display)(void *data, FILE *stream);
    } generic_list_t;
    

    列表结构本身与数据无关,使用void * 表示数据项,并将所有类型感知操作委托给上述指针指示的函数:

    int insert(generic_list_t l, void *data)
    {
      generic_list_node_t *cur = l.head;
      generic_list_node_t *new = malloc(sizeof *new);
      if (new)
      {
        new->data = l.copy(data);
        new->next = NULL;
    
        if (l.head == NULL)
        {
          l.head = new;
        }
        else
        {
          while (cur->next && l.compare(new->data, cur->data) > 0)
            cur = cur->next;
          new->next = cur->next;
          cur->next = new;
          printf("Successfully added ");
          l.display(data, stdout);
          printf(" to list\n");
    
        }
        return 1;
      }
    
      return 0;
    }
    

    1.对于“通用”和“容器”的适当松散定义

    【讨论】:

      【解决方案4】:

      这在嵌入式系统或驱动程序编写中特别有用。 使用函数指针调用函数。

      例如

      struct_my_filesystem.open=my_open;
      struct_my_filesystem.read=my_read;
      

      【讨论】:

        【解决方案5】:

        有时在 C 中您需要调用一个函数,而无需预先知道它的实现。例如。如果您正在开发用于不同项目的独立库。在这种情况下,将函数指针添加到上下文结构并将其传递给库函数是非常有意义的。然后库函数可以在运行时调用您的函数,而无需包含定义它的头文件。

        这确实类似于您在进行面向对象编程时所做的事情。在 C 中,您通常传递上下文变量,例如一个结构,将一组变量和可能对该上下文有意义的函数组合在一起。这接近于 OO 编程中的等价物,您可以在其中实例化一个类并在实例上设置所需的变量。

        【讨论】:

          【解决方案6】:

          这是一个帮助解释函数指针有用性的项目。尝试创建一个提供继承和多态性的基于 c 的库。或者,尝试重新创建“C with Classes”。结构内的函数指针将是至关重要的。 http://www.cs.rit.edu/~ats/books/ooc.pdf

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-12
            • 1970-01-01
            • 1970-01-01
            • 2021-12-17
            • 2018-05-10
            • 2010-12-07
            • 2015-01-24
            • 1970-01-01
            相关资源
            最近更新 更多