我们知道在C中,函数名可以作为函数的入口,那么函数指针就是给这个入口地址取了一个别名。例如:
#include "stdafx.h"
#include<iostream>
#include<string>
#include<cassert>
//定义函数sum
int sum(const int& a,const int& b)
{
assert( (a+b)<INT_MAX && (a+b)>INT_MIN);
return a+b;
}
int (*psum)(const int&,const int&)=sum;// psum为函数指针
typedef int(*fsum1)(const int&,const int&) ;//第二种定义和使用函数指针
fsum1 psum1= sum; //
int main(void )
{
int a = 12,b=15;
int c = psum(a,b);//第一种方式
int d = psum1(a,b);//第二种方式
std::cout<<"use psum:"<<c<<std::endl;
std::cout<<"use psum1:"<<d<<std::endl;
system("pause");
}
这里要解释的是第二种定义和使用函数指针的方式,我们在底层接口封装的时候会经常用到,这里不再多说。
在c++中,静态函数和全局函数的函数指针其定义和调用方式和c中一样,在这里我要强调一下在C++类成员函数指针
// work.cpp : 定义控制台应用程序的入口点。
//using mutex to realize mutithreads
#include "stdafx.h"
#include<iostream>
#include<string>
#include<cassert>
class test_class
{
public:
int do_sum(const int& a,const int& b)// 定义类成员函数
{
std::cout<<"do sum of two elements,result:"<<(a+b)<<std::endl;
return 0;
}
int (test_class::*pdo_sum)(const int& ,const int& );
test_class():a(10),b(20)
{
pdo_sum = &test_class::do_sum;//在构造函数中初始化类成员函数指针
}
private:
int a,b;
};
int test_sample()//在非类成员函数中调用类成员函数指针
{
int a = 2,b=45;
test_class* sample = new test_class;
(*sample.*sample->pdo_sum)(a,b);
if(sample != NULL)
delete sample;
return 0;
}
int main(void )
{
test_class* test = new test_class;
const int a= 13,b=17;
(*test.*test->pdo_sum)(a,b);//主函数中调用
if(test != NULL)
{
delete test;
}
test_sample();// 非类成员函数调用
system("pause");
return 0;
}
可以理解为,把函数指针存在指针数组中,在种手段在大规模测试是经常用到,下面举例说明:
// work.cpp : 定义控制台应用程序的入口点。
//using mutex to realize mutithreads
#include "stdafx.h"
#include<iostream>
#include<string>
#include<cassert>
//定义函数sum
int sum(const int& a,const int& b)
{
assert( (a+b)<INT_MAX && (a+b)>INT_MIN);
return a+b;
}
typedef int(*fsum1)(const int&,const int&) ;//第二种定义和使用函数指针
int main(void )
{
fsum1* sum_test_arr = new fsum1[2];//给数组分配空间,数组类型为fsum1型,fsum1在前面定义过的函数指针
fsum1 psum1= sum;
sum_test_arr[0] = psum1;//把psum1放入数组中
sum_test_arr[1] = psum1;
int a = 12,b=15;
int c = sum_test_arr[0](a,b);//调用
int d = sum_test_arr[1](a,b);//
std::cout<<"use sum_test_arr[0]:"<<c<<std::endl;
std::cout<<"use sum_test_arr[1]:"<<d<<std::endl;
system("pause");
return 0;
}
所谓的回调函数,就是定义某个函数,这个函数本身是用来给其他函数或者是接口调用,声明回调函数的关键词有三个,分别为:_cdecl,_stdcall(这两个都是把函数参数列表压入栈中,就是顺序有差别),_fastcall(这个比较特殊,是把函数参数列表存在寄存器register,如果register空间不足,便自动压入栈中),在这里我要强调的两点是:第一,系统默认的是_cdecl这种声明,第二定义回调函数的时候声明关键词必须保持一致。下面举例说明
a,c语言中回调函数调用定义和调用方法(函数级调用和接口调用两种)
函数级调用:函数级调用是指某个回调函数被某个函数调用下面举例说明
#include "stdafx.h"
#include<iostream>
#include<string>
#include<cassert>
//定义函数sum
#define callback // callback 声明所修饰函数是回调函数 其值可以为空或者是:_cdecl,_stdcall,_fastcall
int callback sum(const int& a,const int& b)
{
assert( (a+b)<INT_MAX && (a+b)>INT_MIN);
return a+b;
}
int (*psum)(const int&,const int&)=sum;// psum为函数指针
typedef int(*fsum1)(const int&,const int&) ;//第二种定义和使用函数指针
inline float average (int& a,int& b ,fsum1 psum1)
{
int c = psum1(a,b);
return (float)c/2;
}
int main(void )
{
int a = 12,b=15;
float e = average(a,b,sum);// average函数调用sum函数(sum函数就是我说的回调函数)
std::cout<< "use average function:\t"<<e<<std::endl;
system("pause");
return 0;
}
从上面代码不难看出,函数级别调用回调函数,就是把函数指针类,作为调用函数的参数传入,这里我要强调的一点是:回调函数声明时候最好加上callback标志符,告诉别人你的这个函数是会回调函数,是给接口或者是其他函数调用的,另外callback的值,在函数定义和声明时候要保持一致,_fastcall的声明理论上可以提高回调函数的速度,但是要考虑你代码的情况和硬件配置包括cache值。
接口级别调用:
接口级调用,就是接口调用回调函数。这个在底层类封装的时候经常用到。下面举例说明:
#include "stdafx.h"
#include<iostream>
#include<string>
#include<cassert>
//定义函数sum
#define callback // callback 声明所修饰函数是回调函数 其值可以为空或者是:_cdecl,_stdcall,_fastcall
int callback sum(const int& a,const int& b)
{
assert( (a+b)<INT_MAX && (a+b)>INT_MIN);
return a+b;
}
int (*psum)(const int&,const int&)=sum;// psum为函数指针
typedef int(*fsum1)(const int&,const int&) ;//第二种定义和使用函数指针
typedef struct user //定义用户接口,接口中有fsum1类型
{
fsum1 lpsum;
int a;
int b;
}*puser;
int main(void )
{
user* USER = new user;
int a = 12,b=15;
USER->a = a;//接口初始化
USER->b = b;
USER->lpsum = sum ;
int c = USER->lpsum(a,b);//调用接口
std::cout<<c<<std::endl;
system("pause");
return 0;
}
b,c++回调函数
下面介绍c++中的回调函数,c++中静态成员函数和全局函数的回调函数机制和c中的是一样的。这里不再介绍,主要介绍类成员函数回调函数和接口回调函数。
通过类this指针实现回调函数
#include "stdafx.h" #include<iostream> #include<string> #include<cassert> class TClass { public: TClass(){} TClass(int& rhs1,int& rhs2):a(rhs1),b(rhs2){} int sum (const int& a,const int& b){return a+b;} static int Wraper_To_Call_Sum(void* p2Object,const int&,const int&);//调用了隐含的this指针 private: int a; int b; }; int TClass::Wraper_To_Call_Sum(void* p2Object,const int& a,const int&b) { TClass* myself = (TClass*)p2Object; return myself->sum(a,b); } int call_a_callback_sum(void* p2Object,int(*callback)(void* p2Object,const int& a,const int& b)) { return callback(p2Object,4,6); } int main(void ) { TClass mytest; int value1 = 15,value2 = 57; int c = mytest.sum(value1,value2);//直接调用类成员函数 int d = mytest.Wraper_To_Call_Sum(&mytest,value1,value2);//类静态函数调用类成员回调函数 int e = call_a_callback_sum((void*)&mytest,TClass::Wraper_To_Call_Sum);//非类函数调用类成员回调函数 std::cout<<c<<"\t"<<d<<"\t"<<e<<std::endl; system("pause"); return 0; }
三、functor(函子)调用函数指针(functor国内有人译做仿函数,这里不做深入探究)
functor可以利用c++模板和多态实现对函数指针的封装。因此你可以