这篇文章 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