为啥将函数作为函数的参数传递?

Posted

技术标签:

【中文标题】为啥将函数作为函数的参数传递?【英文标题】:why pass as argument of a function a function?为什么将函数作为函数的参数传递? 【发布时间】:2019-07-10 17:27:25 【问题描述】:

我有一个小问题。 我正在用 devc++ 学习 C(作为开始),我已经看到作为参数函数,你可以传递一个函数,这没关系,但为什么呢? 例如你可以写为参数:

void myfunc(void(*func)(int))

但是如果你用他的名字和参数简单地调用函数不是更好吗?

例如:

void myfunction ()name of func to call(myargs);  

有区别吗? 看起来一样,但代码更简单更短

编辑:

我只想知道

void map (int (*fun) (int),int x[ ], int l) 
    for(i = 0; i < l; i++)
    x[i] = fun(x[i]);

为什么你用这个来代替:

void map (int x[ ], int l) 
    for(i = 0; i < l; i++)
    x[i] = nameoffunction(yourargument);

【问题讨论】:

你的意思是,例如,qsort() 需要一个函数作为参数?用户函数由qsort调用,对数据项进行比较,否则对函数没有意义,只提供排序机制。 ... 或者你的意思是,函数的唯一工作是调用另一个函数?这样做是为了可以将调用“修补”到另一个函数,或者在途中检查或修改其参数。例如,我可能打算写一个库函数的替代品,但现在我只调用原始函数。请提供一个示例,因为您的问题包含两种情况的示例。 因为:将函数作为参数传递可以让你用同一个数组做不同的事情。您可能有一个子函数递增int,而另一个子函数递减int。你有一个解析数组的函数,并且可以按照它被告知的方式修改每个元素。 nameofyourfunc(yourargs) type(*newnamefunc)(typeofargument)?只有这件事。只是代码少了还是我错了? @wisepeople 你忽略了一个事实,你只是使用function_name(args) 你被那个功能困住了。通过传递一个函数作为参数,调用者可以改变调用函数的选择。这与传递 int 参数而不是在函数体中硬编码一个整数没有什么不同。 【参考方案1】:

如果您希望函数根据用户的需要做不同的事情,您可以使用函数指针作为参数。

这是一个简单的例子:

#include <stdio.h>

int add(int x, int y)

    return x + y;


int subtract(int x, int y)

    return x - y;


int multiply(int x, int y)

    return x * y;


int divide(int x, int y)

    return x / y;


int operation(int x, int y, int (*func)(int, int))

    printf("  x=%d, y=%d\n", x, y);
    return func(x,y);


int main()

    int x = 8, y = 4;

    printf("x+y=%d\n", operation(x,y,add));
    printf("x-y=%d\n", operation(x,y,subtract));
    printf("x*y=%d\n", operation(x,y,multiply));
    printf("x/y=%d\n", operation(x,y,divide));
    return 0;
 

【讨论】:

【参考方案2】:

一个很好的例子是经典的排序功能qsort。这是一个库函数,这意味着您只能访问它的原型。为了使qsort 通用,您必须编写自己的比较函数。常规整数的典型实现如下所示:

int cmpfunc (const void * a, const void * b)

   return ( *(int*)a - *(int*)b ); 

然后,如果您有一个整数数组 arr,您可以使用 qsort(arr, sizeof(arr), cmpfunc) 对其进行排序

你可能会问为什么这不是在qsort 函数中内置的?毕竟,很容易让它同时适用于浮点数和整数。是的,但是想象一下,如果你有一个结构数组,看起来像这样:

struct 
    char *firstname;
    char *lastname;
    int age;
 persons[10];

你会如何排序?嗯,这并不明显。你可能想要这三个。在这种情况下,编写三个不同的比较函数。

【讨论】:

【参考方案3】:
我只想知道
void map (int (*fun) (int),int x[ ], int l) 
    for(i = 0; i < l; i++)
    x[i] = fun(x[i]);
为什么你用这个而不是:
void map (int x[ ], int l) 
    for(i = 0; i < l; i++)
    x[i] = nameoffunction(yourargument);

让我们用一个问题来回答这个问题 - 如果您想要执行不止一种类型的映射怎么办?如果你想同时映射 x2√x 怎么办?

你当然可以做类似的事情

void map( int x[], int l, int type )

  for ( int i = 0; i < l; i++ )
  
    if ( type == MAP_SQUARED )
      x[i] = int_square( x );
    else if ( type == MAP_ROOT )
      x[i] = int_root( x );
    ...
  

这可行,但难以阅读且维护麻烦 - 每次您想要执行新映射时,都必须向 map 函数添加一个新案例。

对比一下

void map( int x[], int l, int (*fun)(int) )

  for ( int i = 0; i < l; i++ )
    x[i] = fun( x[i] );

...
map( x, l, int_square );
map( y, l, int_root );

您不必破解 map 函数来获得不同的映射 - 您只需传递对单个元素进行操作的函数。如果你想执行一个新的映射,你所要做的就是编写一个新函数——你根本不需要编辑map 函数。

C 标准库在多个地方使用这种形式的委托,包括 qsort 函数(允许您以任何顺序对任何类型的数组进行排序)和 signal 函数(允许您更改程序的反应方式)动态中断)。

【讨论】:

以上是关于为啥将函数作为函数的参数传递?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们将视图和上下文对象作为函数中的参数传递,API 22 [关闭]

C语言中,数组名作为函数参数,属于啥传递,为啥?

数组名作为函数的参数属于啥传递为啥

为啥我不能将常量数组作为参数传递?

如果我尝试在不同的公共类中将数组作为参数传递,为啥我的构造函数无法在 Java 中编译?

为啥将 ClientID 传递给 javascript 函数会传递整个控件?