1、函数指针的语法基础
【函数指针的定义、初始化、使用】
对函数名去多少个&,都不起作用,都是一样的,都还是它本身test。
如:test、&test、&&test、&&&test都表示函数的入口地址
同样:
对函数名去多少个*,都不起作用,都是一样的,都还是它本身test。
如:test、*test、**test、***test都表示函数的入口地址
/*
定义函数指针:有两种方法
1.方法一
① C语言中通过typedef为函数类型重命名:typedef 返回类型 FUNC(形参列表);
typedef void FUNC(int ,int ); //先给函数重命名为FUNC
② 用FUNC定义一个FUNC类型的函数指针pointer
FUNC *pointer; //再用FUNC定义一个FUNC类型的函数指针pointer
2.方法二
void (*pointer)(int ,int); //直接定义一个函数指针pointer
*/
#include <iostream>
using namespace std;
typedef void FUNC(int); //给“参数是int,返回类型是int”的函数重命名为FUNC
void test(int i)
{
cout<<"test()"<<endl;
}
int main()
{
FUNC *pointer = NULL; //1.用FUNC定义一个函数指针pointer
pointer = &test; //2.用test函数的入口地址初始化函数指针pointer //等价于pointer = test;
(*pointer)(100); //3.此处表示函数调用,其中*pointer表示函数名
return 0;
}
【同志们,注意了:重点来了】
一个函数的形参、实参如下:
形参:(已经初始化的)函数指针
实参:函数指针
可以在这个函数中,通过实参传递给形参,进而找到形参指向的函数的入口地址,就可以调用形参指向的函数了====>总结为:一个函数的形参为函数指针,可以调用该函数指针指向的函数。下面的程序案例只是简单的讲解用法,没有什么实际意义,程序案例见下:
#include <iostream>
using namespace std;
int add(int a,int b)
{
return a+b;
}
void gg(int (*p)(int,int),int a,int b) //函数指针作函数参数
{//在这个函数里面,可以通过这个函数指针,调用外部的函数,形成一个回调
cout<<(*p)(a,b)<<endl; //在被调函数中,使用传入的函数指针
}
int main()
{
int (*p)(int,int); //定义一个函数指针
p = &add; //初始化函数指针
gg(p,1,2); //函数指针作形参
}
==================================================================================
【讲解】正常情况下,我们都是去调用动态库的代码,但是有一天,动态库的代码要调用我们写的代码,这样就形成了回调!
加载动态库的两种方式:
1.静态调用:编译器帮我们加载
2.动态调用:自己手工的加载
HINSTANCE hDll;//定义一个句柄
hDll=LoadLibrary("F:\\DLL.dll");//1.动态加载DLL模块句柄:加载动态库
if(hDll) //如果加载成功
{
//2.定义一个函数指针,去接受获得的GetProcAddress函数返回的函数的入口地址
typedef int (*pAdd)(int,int) = NULL; //定义一个函数指针类型pAdd
pAdd ptr = (pAdd)GetProcAddress(hDll,"add");;//用函数指针类型pAdd,去定义一个函数指针变量ptr
if(ptr)
{
int result=ptr(2,3);
printf("%d",result);
}
FreeLibrary(hDll);//释放已经加载的DLL模块
}
—————————————————————————————————————————-
【动态库回调函数的实现的两种方式】
如何把一个普通的DLL动态库变成一个业务模型,需要做的工作
需要把第三方业务入口传进来(即回调函数的入口地址传进来),传进来的方式有两种:
方式一:回调函数的入口地址直接放在DLL中的参数中
方式二:回调函数的入口地址缓存到框架库中
【方式一案例】
/*
Question1:如何实现了上层的业务数据数组的遍历?
ANSWER1:
STL不知道上层的业务数据类型是什么样的,因此写出遍历上层的业务数据的函数callbackFunc_for_each,
再用STL中的for_each函数去回调callbackFunc_for_each函数---->这样就实现了上层的业务数据数组的遍历。
Question1:如何实现了上层的业务数据数组的排序?
ANSWER1:
STL不知道上层的业务数据类型是什么样的,因此写出排序上层的业务数据的函数callbackFunc_sort,
再用STL中的sort函数去回调callbackFunc_sort函数---->这样就实现了上层的业务数据数组的排序。
*/
【代码见下】
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct teacher
{
char name[100];
int age;
};
void callbackFunc_for_each(struct teacher& t) //回调函数
{
cout<<t.name<<" "<<t.age<<endl;
}
int callbackFunc_sort(struct teacher& t1,struct teacher& t2)//回调函数
{
return t1.age>t2.age;
}
int main()
{
struct teacher t1 = {"T1",30};
struct teacher t2 = {"T2",40};
struct teacher t3 = {"T3",50};
vector<struct teacher> vec;
vec.push_back(t1);
vec.push_back(t2);
vec.push_back(t3);
//【解释】for_each是DLL中的函数,要使for_each函数适应于所有的业务模型,应当利用
//回调函数callbackFunc_for_each,该回调函数是自己手工写的!
for_each(vec.begin(),vec.end(),callbackFunc_for_each); //callbackFunc_for_each是回调函数
sort(vec.begin(),vec.end(),callbackFunc_sort); //callbackFunc_sort是回调函数
for_each(vec.begin(),vec.end(),callbackFunc_for_each);
}
【方式二案例】