C++函数指针在回调函数中的使用

一、函数指针的定义

函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针指向的是函数,其实与用指针指向变量一样。在代码编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向这个函数地址的指针变量后,可用该指针变量找到函数的地址进而调用函数。代码实例:

需要注意的数定义函数指针时的括号不可以省略,例如:

//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 <iostream>
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 <iostream>
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  596214569@qq.com.
*
*  This file is part of functionpoint test project.
*
*  @file     FunctionTest.h
*  @brief
*  Details.
*
*  @author   LL
*  @email    596214569@qq.com
*  @version  1.0.0.1
*  @date     596214569@163.com
*
*----------------------------------------------------------------------------
*  Remark         : Description
*----------------------------------------------------------------------------
*  Change History :
*  <Date>     | <Version> | <Author>       | <Description>
*----------------------------------------------------------------------------
*  2020/04/21 | 1.0.0.1   | LL			   | Create file
*----------------------------------------------------------------------------
*
*****************************************************************************/

#include <iostream>
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 <iostream>
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");
}

执行结果:

©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值