回调函数实现的机制是
(1)定义一个回调函数; (2)提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者; (3)当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
编辑本段为什么要使用回调函数
因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。 如果想知道回调函数在实际中有什么作用,先假设有这样一种情况,我们要编写一个库,它提供了某些排序算法的实现,如冒泡排序、快速排序、shell排序、shake排序等等,但为使库更加通用,不想在函数中嵌入排序逻辑,而让使用者来实现相应的逻辑;或者,想让库可用于多种数据类型(int、float、string),此时,该怎么办呢?可以使用函数指针,并进行回调。 回调可用于通知机制,例如,有时要在程序中设置一个计时器,每到一定时间,程序会得到相应的通知,但通知机制的实现者对我们的程序一无所知。而此时,就需有一个特定原型的函数指针,用这个指针来进行回调,来通知我们的程序事件已经发生。实际上,SetTimer() API使用了一个回调函数来通知计时器,而且,万一没有提供回调函数,它还会把一个消息发往程序的消息队列。 另一个使用回调机制的API函数是EnumWindow(),它枚举屏幕上所有的顶层窗口,为每个窗口调用一个程序提供的函数,并传递窗口的处理程序。如果被调用者返回一个值,就继续进行迭代,否则,退出。EnumWindow()并不关心被调用者在何处,也不关心被调用者用它传递的处理程序做了什么,它只关心返回值,因为基于返回值,它将继续执行或退出。 不管怎么说,回调函数是继续自C语言的,因而,在C++中,应只在与C代码建立接口,或与已有的回调接口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或函数符(functor),而不是回调函数。
编辑本段简单的回调函数实现
代码实现
下面创建了一个sortdll的动态链接库,它导出了一个名为CompareFunction的类型--typedef int (__stdcall CompareFunction)(const byte, const byte),它就是回调函数的类型。另外,它也导出了两个方法:Bubblesort()和Quicksort(),这两个方法原型相同,但实现了不同的排序算法。 void DLLDIR __stdcall Bubblesort(byte array,int size,int elem_size,CompareFunction cmpFunc); void DLLDIR __stdcall Quicksort(byte array,int size,int elem_size,CompareFunction cmpFunc); 这两个函数接受以下参数: ·byte array:指向元素数组的指针(任意类型)。 ·int size:数组中元素的个数。 ·int elem_size:数组中一个元素的大小,以字节为单位。 ·CompareFunction cmpFunc:带有上述原型的指向回调函数的指针。 这两个函数的会对数组进行某种排序,但每次都需决定两个元素哪个排在前面,而函数中有一个回调函数,其地址是作为一个参数传递进来的。对编写者来说,不必介意函数在何处实现,或它怎样被实现的,所需在意的只是两个用于比较的元素的地址,并返回以下的某个值(库的编写者和使用者都必须遵守这个约定): ·-1:如果第一个元素较小,那它在已排序好的数组中,应该排在第二个元素前面。 ·0:如果两个元素相等,那么它们的相对位置并不重要,在已排序好的数组中,谁在前面都无所谓。 ·1:如果第一个元素较大,那在已排序好的数组中,它应该排第二个元素后面。 基于以上约定,函数Bubblesort()的实现如下,Quicksort()就稍微复杂一点: void DLLDIR __stdcall Bubblesort(byte array,int size,int elem_size,CompareFunction cmpFunc) { for(int i=0; i < size; i++) { for(int j=0; j < size-1; j++) { //回调比较函数 if(1 == (cmpFunc)(array+jelem_size,array+(j+1)elem_size)) { //两个相比较的元素相交换 byte temp = new byte[elem_size]; memcpy(temp, array+jelem_size, elem_size); memcpy(array+jelem_size,array+(j+1)elem_size,elem_size); memcpy(array+(j+1)elem_size, temp, elem_size); delete [] temp; } } } } 注意:因为实现中使用了memcpy(),所以函数在使用的数据类型方面,会有所局限。 对使用者来说,必须有一个回调函数,其地址要传递给Bubblesort()函数。下面有二个简单的示例,一个比较两个整数,而另一个比较两个字符串: int __stdcall CompareInts(const byte velem1, const byte velem2) { int elem1 = (int)velem1; int elem2 = (int)velem2; if(elem1 < elem2) return -1; if(elem1 > elem2) return 1; return 0; } int __stdcall CompareStrings(const byte velem1, const byte velem2) { const char elem1 = (char)velem1; const char elem2 = (char)velem2; return strcmp(elem1, elem2); } 下面另有一个程序,用于测试以上所有的代码,它传递了一个有5个元素的数组给Bubblesort()和Quicksort(),同时还传递了一个指向回调函数的指针。 int main(int argc, char argv[]) { int i; int array[] = {5432, 4321, 3210, 2109, 1098}; cout << "Before sorting ints with Bubblesort\n"; for(i=0; i < 5; i++) cout << array<< ’\n’; Bubblesort((byte)array, 5, sizeof(array[0]), &CompareInts); cout << "After the sorting\n"; for(i=0; i < 5; i++) cout << array<< ’\n’; const char str[5][10] = {"estella","danielle","crissy","bo","angie"}; cout << "Before sorting strings with Quicksort\n"; for(i=0; i < 5; i++) cout << str<< ’\n’; Quicksort((byte)str, 5, 10, &CompareStrings); cout << "After the sorting\n"; for(i=0; i < 5; i++) cout << str<< ’\n’; return 0; } 如果想进行降序排序(大元素在先),就只需修改回调函数的代码,或使用另一个回调函数,这样编程起来灵活性就比较大了。
mid是pb的一个字符处理函数,来截取字符串其中一部分字符
语法格式:
Mid ( string, start {, length } )
例:
Mid ( 'abcd', 2 ) //返回‘bcd’Mid ( 'abcd', 1,2 ) //返回‘ab’
需要注意的是,类似len和lenw,该函数也有midw。区别在于汉字的处理。len、mid:1个汉字长度为2,而lenW、midW:无论是1个汉字还是1个字母长度都为1。
Retrieve()功能:让数据窗口控件从数据库中提取数据。如果为该函数提供了参数,那么这些参数的值将用作数据窗口的对象SQL SELECT语句的提取参数。
语法:dwcontrolRetrieve ( {, argument, argument } )
参数:dwcontrol:数据窗口控件名
argument:向数据窗口对象的SQL SELECT语句提供的检索参数
返回值:Long。函数执行成功时,返回显示在数据窗口中的数据行的行数(即主缓冲区的数据行数);函数执行失败时返回-1。如果任何参数的值为NULL,则Retrieve()函数返回NULL。
用法:使用Retrieve()函数检索出数据之后,系统自动执行数据窗口对象的过滤条件,不满足过滤条件的行被立即移动到过滤缓冲区中,Retrieve()函数返回的行数不包括移动到过滤缓冲区中的行。
在执行Retrieve()函数之前,必须用数据窗口控件的对象函数SetTransObject()或SetTrans()为数据窗口控件设置事务对象。当使用SetTransObject()函数时,在调用之前,需要使用嵌入式SQL语句CONNECT建立事务对象与数据库的连接。
下,执行Retrieve()后,数据窗口中原有的数据被丢弃,并用新的数据来取代。如果想改变这种缺省 *** 作,那么可以通过在数据窗口控件的RetrieveStart事件中编写代码来实现,方法很简单,只要在该事件的事件处理程序中放上语句:Return 2即可。这时,Retrieve()检索出的数据增加到数据窗口原有数据的后面。
如果数据窗口控件中的数据窗口对象需要检索参数,而Retrieve()函数中又没有提供这些参数,那么执行Retrieve()函数时,系统将显示一个对话框,让用户键入检索参数的取值。
Exp1:不带参数的Retrieve
long ll_rows
dw_mainSetTransObject(SQLCA)
ll_rows = dw_mainRetrieve()
IF ll_rows < 1 THEN MessageBox( "数据库错误", "没有检索到数据。")
Exp2:带参数的Retrieve
假定数据窗口控件dw_emp中的数据窗口对象使用下面的SQL SELECT语句:SELECT Name, empsal, salesrgn From Employee
WHERE empsal > :Salary and salesrgn = :Region
那么下面的语句使数据窗口控件dw_emp1从数据库中提取salary大于50000且地区值为北京的数据:
dw_1Retrieve(50000, "北京")
希望对你有所帮助!:-)
因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
想知道回调函数在实际中有什么作用?先假设有这样一种情况:我们要编写一个库,它提供了某些排序算法的实现(如冒泡排序、快速排序、shell排序、shake排序等等),为了能让库更加通用,不想在函数中嵌入排序逻辑,而让使用者来实现相应的逻辑;或者,能让库可用于多种数据类型(int、float、string),此时,该怎么办呢?可以使用函数指针,并进行回调。
回调可用于通知机制。例如,有时要在A程序中设置一个计时器,每到一定时间,A程序会得到相应的通知,但通知机制的实现者对A程序一无所知。那么,就需一个具有特定原型的函数指针进行回调,通知A程序事件已经发生。实际上,API使用一个回调函数SetTimer()来通知计时器。如果没有提供回调函数,它还会把一个消息发往程序的消息队列。
另一个使用回调机制的API函数是EnumWindow(),它枚举屏幕上所有的顶层窗口,每个窗口都可以通过它调用另一个程序提供的函数,并传递窗口的处理程序。例如:如果被调用者返回一个值,就继续进行迭代;否则,退出。EnumWindow()并不关心被调用者在何处,也不关心被调用者用它传递的处理程序做了什么,它只关心返回值,因为基于返回值,它将继续执行或退出。
不管怎么说,回调函数是继承自C语言的。在C++中,应只在与C代码建立接口或与已有的回调接口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或仿函数(functor),而不是回调函数。
1,建 DW 对象,以父节点关键字数据为参数,检索指定父节点的子项,选择的列包括TV节点所需要的数据,包括是否有了项等。
2,写类似这样的函数 uf_tree_redraw(string as_parent, long al_phandle):
a函数具备两个参数,父节点关键字和父节点已经插入在TV中的handle
b函数完成的功能有建 datastore lds_tmp,选择第1步中的DW 对象做dataobject,检索;
判断as_parent 是否根节点,如果是,则 tvdelitem(0);
以lds_tmprowcount() 做循环,循环在 al_phandle 下插入子节点,并用变量装载插入的子节点的handle,插入的时候检查该新节点是否有子项,若有,则递归调用 uf_tree_redraw(string as_parent, long al_phandle) 即可。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)