c++ 函数指针与类模板的使用(二)

        这篇文章 c++ 普通函数指针与类模板的使用(一) 介绍了函数指针与模板的使用,下面是一个改进版本,以前的项目中基本就是这个用法了。

#include <stdio.h>
#include <stdlib.h>

template <typename R, typename T1, typename T2>

class CFunctionProc
{
	typedef R (*funcProc)(T1, T2);
public:
	bool attach(funcProc func)
	{
		mFuncProc = func; 
		return true;
	}

	bool detach()
	{
		mFuncProc = nullptr; 
		return true;
	}

	void invoke(T1 a, T2 b)
	{
		mFuncProc(a, b);
	}

	funcProc getFuncProc() const
	{
		return mFuncProc;
	}
private:
	funcProc mFuncProc;
};

template <typename R, typename T1, typename T2>
class CSignal
{
	typedef CFunctionProc<R, T1, T2> Proc;
	typedef R (*funcProc)(T1, T2);
	enum SLOTSTATE
	{
		SLOT_EMPTY, //还没赋值
		SLOT_VALUE, //已经赋值
	};

	struct signalslot
	{
		Proc proc;
		SLOTSTATE state;
	};
private:
	int mSlots;	//最大可以注册函数指针数量
	signalslot	*mSignalSlots;
public:
	CSignal(int size): mSlots(size), mSignalSlots(NULL)
	{
		mSignalSlots = new signalslot[mSlots]; //总共 new mSlots 个signalslot
		
		//初始化都是空的
		for(int i = 0; i < mSlots; i++)
		{
			mSignalSlots[i].state = SLOT_EMPTY;
		}
	}
	
	~CSignal()
	{
		for(int i = 0; i < mSlots; i++)
		{
			mSignalSlots[i].state = SLOT_EMPTY;
		}

		delete []mSignalSlots;
	}
	
	bool attach(funcProc proc)
	{
		for(int i = 0; i < mSlots; i++)
		{
			if(mSignalSlots[i].state == SLOT_EMPTY) //这里是按顺序注册函数指针
			{
				mSignalSlots[i].proc.attach(proc);
				mSignalSlots[i].state = SLOT_VALUE;
				return true;
			}
		}
		printf("slots is full\n");
		return false;
	}
	
	bool detach(funcProc func)
	{
		for(int i = 0; i < mSlots; i++)
		{
			if(mSignalSlots[i].proc.getFuncProc() == func) //卸载指定的函数指针
			{
				mSignalSlots[i].proc.detach();
				mSignalSlots[i].state = SLOT_EMPTY;
				return true;
			}
		}
		return false;
	}

	/*
	* 重载(),仿函数方式使用
	* 使用方式为: 
	* CSignal<void, int, int> signal;
	* signal.attach();
	* signal(x, y);
	*/
	R operator()(T1 a, T2 b) 
	{
		for(int i = 0; i < mSlots; i++)
		{
			if(mSignalSlots[i].state == SLOT_VALUE)
			{
				mSignalSlots[i].proc.invoke(a, b);
			}
		}
	}
};

void func1(int x, int y)
{
	printf("in func1, x + y = %d\n", x + y);
}

void func2(int x, int y)
{
	printf("in func2, x + y = %d\n", x + y);
}

void func3(int x, int y)
{
	printf("in func3, x + y = %d\n", x + y);
}


void func4(int x, int y)
{
	printf("in func4, x + y = %d\n", x + y);
}

int main()
{
	CSignal<void, int, int> signal(3);
	signal.attach(func1);
	signal.attach(func2);
	signal.attach(func3);
	signal.attach(func4);
	
	signal(4, 5);
	return 0;
}

  

         这个在实际项目中用得比较多,典型的就是设计模式中的 观察者模式,比如设备配置的改变触发一系列的事件,只需要将关心的配置与signal相关联,然后再注事件处理函数注册进去,配置管理层在感知到配置修改时,调用signal() 即可。

        这两篇都是讲普通的函数指针,而成员函数指针要复杂得多,可以参考这篇详细讲解成员函数指针的文章:https://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值