函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针指向的是函数,其实与用指针指向变量一样。在代码编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向这个函数地址的指针变量后,可用该指针变量找到函数的地址进而调用函数。代码实例:
需要注意的数定义函数指针时的括号不可以省略,例如:
//pfadd 是一个指向函数的指针变量,所指函数的返回值类型为整型
int (*pfadd)(int a, int b);
//pfadd 是函数名,此函数的返回值类型为整型指针
int *pfadd(int a, int b);
// 这也等同于
int* pfadd(int a, int b);
函数指针具有的是指针的特性,即指向地址,那么也就是说可以通过函数指针找到对应地址中的函数,需要区分的是一个函数指针变量,它是一个指向一种函数地址的变量,那么这个变量值也就是可以改的,这个变量值指向不同的函数地址所找到的函数也就不同,例如上面的 pfadd , 如果A类中有一个函数为
int Add(int a, int b);
B类中有一个函数为
int Del(int a, int b);
那么pfadd指向这两个函数所执行的操作自然是不同的;
函数指针与普通指针不同的一点是函数指针只能指向一个地址,无法在这个地址的基础上进行加减等操作,也就是无法扩展寻址;
了解了函数指针的概念之后,很容易想到函数指针所具有的抽象性可以为写代码提供的便利,最简单的就是通过函数指针完成回调函数,代码例子:
类CTestController:
#pragma once
#include
using namespace std;
typedef int (*pf) (int, int);
class CTestController
{
public:
CTestController() {};
~CTestController() {};
void Print(const int a,const int b)
{
cout << m_pf(a, b) << endl;
}
pf m_pf;
};
主程序:
// TesteApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
using namespace std;
#include "CTestController.h"
/// 加法函数
int Add(const int a,const int b)
{
return a + b;
}
/// 减法函数
int Del(const int a, const int b)
{
return a - b;
}
int main()
{
CTestController pController;
cout << "我是加法" << endl;
pController.m_pf = Add;
pController.Print(9, 4);
cout << "我是减法" << endl;
pController.m_pf = Del;
pController.Print(9, 4);
system("pause");
}
执行结果:
可以看到,对于CTestController来说,不需要知道 m_pf 里面具体做了什么,只需要当有必要时执行一遍 m_pf 即可;
Functest.h 文件:
/******************************************************************************
Copyright (C) 2020 LL [email protected].
*
* This file is part of functionpoint test project.
*
* @file FunctionTest.h
* @brief
* Details.
*
* @author LL
* @email [email protected]
* @version 1.0.0.1
* @date [email protected]
*
*----------------------------------------------------------------------------
* Remark : Description
*----------------------------------------------------------------------------
* Change History :
* | | |
*----------------------------------------------------------------------------
* 2020/04/21 | 1.0.0.1 | LL | Create file
*----------------------------------------------------------------------------
*
*****************************************************************************/
#include
using namespace std;
class CVoidClass
{
};
class CFuntionCLassA
{
public:
CFuntionCLassA() {};
void TestAllFinished()
{
cout << "All Finished" << endl;
}
};
class CFuntionCLassB
{
public:
CFuntionCLassB() {};
void TestBegin(int nint)
{
cout << "Begin" << nint << endl;
}
void TestOneFinished(int nint, int nn)
{
cout << "One Finished" << nint << endl;
cout << "One Finished" << nn << endl;
}
};
typedef void (CVoidClass::* Callback_OneBegin)(int pInt);
typedef void (CVoidClass::* Callback_OneFinished)(int pInt, int nInt);
typedef void (CVoidClass::* Callback_AllFinished)();
struct MultiCallBack
{
MultiCallBack(CVoidClass* objOne, Callback_OneFinished finish, Callback_OneBegin begin, CVoidClass* objTwo, Callback_AllFinished two)
{
this->objOne = objOne;
this->oneBegin = begin;
this->oneFinish = finish;
this->objTwo = objTwo;
this->two = two;
}
~MultiCallBack() {}
CVoidClass* objOne; // one成员函数的类实例
Callback_OneBegin oneBegin; // CallBackClass的成员函数,加载一个模组前,会同步调用
Callback_OneFinished oneFinish; // CallBackClass的成员函数,加载完成一个模组后,会同步调用
CVoidClass* objTwo; // all成员函数的类实例
Callback_AllFinished two; // CallBackClass的成员函数,加载完成所有模组后,会同步调用
};
主程序:
// TesteApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
using namespace std;
#include "FunctionTest.h"
#define MakeMultiCallback(objOne, finish, begin, objTwo, two) \
(MultiCallBack((CVoidClass*)objOne, (Callback_OneFinished) finish, (Callback_OneBegin) begin, (CVoidClass*) objTwo, (Callback_AllFinished) two))
int main()
{
CFuntionCLassA* a = new CFuntionCLassA();
CFuntionCLassB* b = new CFuntionCLassB();
MultiCallBack pMc = MakeMultiCallback(b, &CFuntionCLassB::TestOneFinished, &CFuntionCLassB::TestBegin, a, &CFuntionCLassA::TestAllFinished);
(pMc.objOne->*pMc.oneBegin)(1);
(pMc.objOne->*pMc.oneFinish)(1,2);
(pMc.objTwo->*pMc.two)();
system("pause");
}
执行结果: