回调的原理、实现与应用(1)

什么是回调

上一篇文章中讲了“函数的指针”,那么函数指针有什么用呢?一个最常用的地方就是回调。

什么回调?维基百科是这样解释的:回调是一段可执行的代码通过参数传递给别一段代码,以期望在一个合适的时间调用这个参数(可执行的代码)。

参考:In computer programming, a callback is a piece of executable code that is passed as an argument to other code, which is expected to call back(execute) the argument at some convenient time.

如果你已明白回调或理解上面这一句话,可以漂过,感觉头昏的请往下看。

从一个需求开始

先不扯淡,直接拿事实说话。假设有这么一个需求:

有一Person类定义如下:

struct Person

{

int age;

float weight;

float height;

};

现要对Person的一组对象进行排序,但并没有确定根据什么规则来排序,有时需要根据年龄进行排序,有时需要根据身高进行排序,有时可能是根据身高和体重的综合情况来排序,还有可能……

你可能会想到这样写,定义三个函数分别根据年龄、体重、身高进行排序:

void SortByAge(Person* persons, int count);

void SortByWeight(Person* persons, int count);

void SortByHeight(Person* persons, int count);

如果要根据身高和体重的综合情况来排序,那你还得再定义一个函数。这样是不是代码冗余且很繁琐?但如果你会用回调,这个问题就会很简单。

用回调实现对Person的排序:

typedef int (*Compare)(const Person&, const Person&);

//交换两个元素
void swap(Person* p1, Person *p2)
{
	Person p = *p1;
	*p1 = *p2;
	*p2 = p;
}
//排序(本例中采用冒泡排序)
void PersonSort(Person* persons, int count, Compare pCompare)
{
	for (int i = 0; i < count-1; i ++)
	{
		for (int j = 0; j < count - i -1; j++)
		{
			if (pCompare(persons[j], persons[j+1]) > 0)
			{
				swap(persons+j, persons+j+1);
			}
		}
	}
}

如果你要根据年龄来进行排序,只要实现一个Compare类型的函数,再调用上面的PersonSort函数就可以实现根据年龄排序的功能。如:

int CompareByAge(const Person& p1, const Person& p2)
{
	return p1.age - p2.age;
}

void TestCallBack()
{
	//创建Person的一组对象persons,对象中的各个值为0到100的随机数
	srand((unsigned)time(NULL));
	Person persons[10];
	for(int i = 0; i < 10; i ++)
	{
		persons[i].age = rand()%100;
		persons[i].weight = rand()%100;
		persons[i].height = rand()%100;
	}
	//【todo】
	//根据年龄进行排序。
	PersonSort(persons, 10, CompareByAge);

	for(int i = 0; i < 10; i ++)
	{
		std::cout << persons[i].age << "\t" <<	persons[i].weight << "\t" << persons[i].weight << std::endl;
	}
}

说明:以上调用TestCallBack函数时需要包含头文件<iostream>、<time.h>

这样如果需求发生变更(如要根据每个Person身高和体重的总和来排序),只需求再定义一个Compare类型的函数,而不用再对PersonSort函数做任何改动。如下:

int CompareByHeightWeight(const Person& p1, const Person& p2)
{
	return (p1.height + p1.weight) - (p2.height + p2.weight);
}

void TestCallBack()
{
	//创建Person的一组对象persons,对象中的各个值为0到100的随机数
	srand((unsigned)time(NULL));
	Person persons[10];
	for(int i = 0; i < 10; i ++)
	{
		persons[i].age = rand()%100;
		persons[i].weight = rand()%100;
		persons[i].height = rand()%100;
	}
	//【todo】
	//根据年龄进行排序。
	PersonSort(persons, 10, CompareByHeightWeight);

	for(int i = 0; i < 10; i ++)
	{
		std::cout << persons[i].age << "\t" <<	persons[i].weight << "\t" << persons[i].height << "\t" << persons[i].weight + persons[i].height << std::endl;
	}
}

通过上面一个实例的分析,应该对回调有所了解和认识了吧!回调函数说白了就是定义一个函数,然后通过参数传递给另一个函数调用。回调不仅是一种技术,更是一种编程思想,上面是通过回调函数来实现的,但它不仅限于回调函数,也可以用其它的技术实现(如面向对象的实现)。如果想更深入的了解,请看后续的文章。

时间: 2024-10-26 02:03:34

回调的原理、实现与应用(1)的相关文章

Block、委托、回调函数原理剖析(在Object C语境)——这样讲还不懂,根本不可能!

开篇:要想理解Block和委托,最快的方法是搞明白“回调函数”这个概念. 做为初级选手,我们把Block.委托.回调函数,视为同一原理的三种不同名称.也就是说,现在,我们把这三个名词当成一回事.在这篇文章内,Block就是回调函数,委托也是回调函数,不再作详细的区分了.OK,Action! 那么,什么是回调函数?“回调”概念的主语是谁? 举个栗子(伪代码): 首先有个类,我们姑且称之为A类吧. A.h 文件 //声明回调函数:给指定的员工发放工资 -(void)paySalaryForStaff

【转】回调的原理、应用

什么是回调 什么回调?维基百科是这样解释的:回调是一段可执行的代码通过参数传递给别一段代码,以期望在一个合适的时间调用这个参数(可执行的代码). 参考:In computer programming, a callback is a piece of executable code that is passed as an argument to other code, which is expected to call back(execute) the argument at some co

谈谈-Android中的接口回调技术

Android中的接口回调技术有很多应用的场景,最常见的:Activity(人机交互的端口)的UI界面中定义了Button,点击该Button时,执行某个逻辑. 下面参见上述执行的模型,讲述James对Android接口回调技术的理解(结合前人的知识和自己的实践). 使用一个比喻很形象地说明:客户端有个疑问打电话请教服务端,但服务端无法现场给出解答,相互之间约定:服务端一旦有答案,使用电话的方式反馈给客户端. 以上有三个主体:客户端.服务端和接口(方式). 接口回调的原理框图说明: Demo界面

不用回调方法捕获数据包

这次将用 pcap_next_ex() 函数代替上一次的 pcap_loop()函数. pcap_loop()函数是基于回调的原理来进行数据捕获,这是一种精妙的方法,并且在某些场合中,它是一种很好的选择. 然而,处理回调有时候并不实用 -- 它会增加程序的复杂度,特别是在拥有多线程的C++程序中. 可以通过直接调用pcap_next_ex() 函数来获得一个数据包 -- 只有当编程人员使用了 pcap_next_ex() 函数才能收到数据包. 这个函数的参数和捕获回调函数的参数是一样的 -- 它

编程思想之回调

原文:http://blog.csdn.net/luoweifu/article/details/41465289 <回调的原理.实现与应用>一文中已经初步讲了回调的原理和应用,并就一个实际需求用函数的方式实现了回调应用.但回调并不仅限于回调函数,可以有很多不同的现实方式.回调与其说是一种技术,不如说是一种编程思想,我们在各种计算机语言中都能看到它的踪影.我们以<回调的原理.实现与应用>一文中提到的需求为例,看看C++.JavaScript.Java等各种语言下回调的实现方式. 有

接口_ _接口回调机制

在Android中到处可见接口回调机制,尤其是UI事件处理方面,本文给大家介绍android接口回调机制,涉及到android接口回调相关知识,对本文感兴趣的朋友可以参考下本篇文章 在使用接口回调的时候发现了一个经常犯的错误,就是回调函数里面的实现有可能是用多线程或者是异步任务去做的,这就会导致我们期望函数回调完毕去返回一个主函数的结果,实际发现是行不通的,因为如果回调是多线程的话你是无法和主函数同步的,也就是返回的数据是错误的,这是非常隐秘的一个错误.那有什么好的方法去实现数据的线性传递呢?先

winPcap_6_不用回调方法捕获数据包

用 pcap_next_ex() 函数代替 _5_ 中的 pcap_loop()函数: pcap_loop()函数是基于回调的原理来进行数据捕获,这是一种精妙的方法,并且在某些场合中,它是一种很好的选择. 然而,处理回调有时候并不实用 -- 它会增加程序的复杂度,特别是在拥有多线程的C++程序中. 可以通过直接调用pcap_next_ex() 函数来获得一个数据包 -- 只有当编程人员使用了 pcap_next_ex() 函数才能收到数据包. 这个函数的参数和捕获回调函数的参数是一样的 -- 它

回调之编程思想

<回调的原理.实现与应用>一文中已经初步讲了回调的原理和应用,并就一个实际需求用函数的方式实现了回调应用.但回调并不仅限于回调函数,可以有很多不同的现实方式.回调与其说是一种技术,不如说是一种编程思想,我们在各种计算机语言中都能看到它的踪影.我们以<回调的原理.实现与应用>一文中提到的需求为例,看看C++.JavaScript.Java等各种语言下回调的实现方式. 有一Person类,有年龄(age),体重(weight),身高(height)三个属性.现要对Person的一组对象

转载:C#实现接口回调

通常情况下,我们创建一个对象,并马上直接去使用它的方法.然而,在有些情况下,希望能在某个场景出现后或条件满足时才调用此对象的方法.回调就可以解决这个“延迟调用对象方法”的问题.这个被调用方法的对象称为回调对象. 实现回调的原理简介如下: 首先创建一个回调对象,然后再创建一个控制器对象,将回调对象需要被调用的方法告诉控制器对象.控制器对象负责检查某个场景是否出现或某个条件是否满足.当此场景出现或此条件满足时,自动调用回调对象的方法. 以下为C#实现回调的一个小例子. using System; u