函数对象与闭包的误区 函数的指针 高阶函数 将一部分处理以函数对象的形式转移到外部从而实现了算法的通用化

 

1、函数对象与闭包的误区

有一些编程语言中提供了函数对象这一概念,我知道有些把这个叫做闭包(Closure),但其实这种理解是不准确的,因为函数对象不一定是闭包。不过话说回来,要理解闭包,首先要理解函数对象。

函数对象是作为对象来使用的函数。不过,这里的对象不一定是面向对象中所指的那个对象,而更像是编程语言所操作的数据这个意思。

 

C语言的函数对象

#include <stdio.h>
int two(int x) {
	return x*2;
}
int three(int x) {
	return x*3;
}
int main(int argc,char **argv) {
	int (*times)(int);
	int n=2;
	if(argc==1)times=two;
	else
		times=three;
	printf("times(%d)=%d\n",n,times(n));
}

  C语言中,我们可以获取一个函数的指针,并通过指针间接调用该函数。这就是C语言概念中的对象。

 

 int (*times)(int);

这是对指针型变量times的声明:变量times,是指向一个拥有一个int型参数,并返回int值的函数的指针。

 其中if语句:当传递给程序的命令行参数为0个时,将函数two(的指针)赋值给变量times;

                   一个以上,则将函数three的指针赋值给times。

 

2、函数对象对编程的用途

函数对象,也就是将函数作为值来利用的方法,其最大的用途就是高阶函数。

所谓高阶函数,就是用函数作为参数的函数。

 

设想一个对数组排序的函数。这个函数是用C语言编写的,在API设计上,应该写成这样:

void sort(int *a,size_t size);

函数接受一个大小为size的整数数组a,并对其内容进行排序。

其缺乏通用性:

a)只能对整数数组进行排序;

b)排序条件无法从外部进行指定。

 

在C语言标准库中,却提供了一个具有通用性的排序函数:qsort。

void qsort(void *base,size_t nmemb,size_t size,int(*compar)(const void *,const void *));

 

#ifndef _CRT_ALGO_DEFINED
#define _CRT_ALGO_DEFINED
void *__cdecl bsearch(const void *_Key,const void *_Base,size_t _NumOfElements,size_t _SizeOfElements,int (__cdecl *_PtFuncCompare)(const void *,const void *));
void __cdecl qsort(void *_Base,size_t _NumOfElements,size_t _SizeOfElements,int (__cdecl *_PtFuncCompare)(const void *,const void *));
#endif

 

 

那么这个通用排序函数qsort是如何克服上述这两个缺点的呢?秘密就隐藏在qsort函数的参数中。

参数base,类型void *,可以接受任何类型的数组

如何对任意类型数组中元素进行比较呢?

qsort函数的第4个参数compar:compar是指向一个带两个参数的函数的指针,并以整数的形式返回比较结果。

 

#include <stdio.h>
#include <stdlib.h>

int icmp(const void *a,const void *b) {
	int x = *(int*)a;
	int y = *(int*)b;
	if(x==y) return 0;
	if(x>y) return -1;
	return 1;
};

int main(int argc,char **argv) {
	int ary[]= {4,7,1,2};
	const size_t alen=sizeof(ary)/sizeof(int);
	size_t i;
	for(i=0; i<alen; i++) {
		printf("ary[%d] = %d\n",i,ary[i]);
	}
	qsort(ary,alen,sizeof(int),icmp);
	for(i=0; i<alen; i++) {
		printf("ary[%d] = %d\n",i,ary[i]);

	}
}

  

 qsort函数是通过将另一个函数作为参数使用,来实现通用排序功能的。高阶函数这样的方式,通过将一部分处理以函数对象的形式转移到外部,从而实现了算法的通用化。

 

 

 

 

 

 

 

 

 

 

闭包  《代码的未来》

posted @ 2019-03-07 23:19  papering  阅读(399)  评论(0编辑  收藏  举报