函数指针与类的使用在实际项目中经常会使用,但更多的情况是在类里声明一个类模板的变量,这个类模板实现了包含某种类型的函数指针,同时这个类模板可以进行多个函数指针的注册,这样就可以实现了一对多的调用情况,这个类似于设计模式中的“观察者模式”,即一个动作的发生可以有多个响应。
下面看一个简单的将函数指针注册到类里的例子,如:
#include <stdio.h>
#include <stdlib.h>
class CFunc_ptr
{
typedef int (*funcProc)(int, int); //声明函数指针,只能针对一种类型
public:
CFunc_ptr(): m_funcProc(nullptr)
{
}
~CFunc_ptr()
{
m_funcProc = nullptr;
}
bool attach(funcProc func)
{
m_funcProc = func;
return true;
}
bool detach()
{
m_funcProc = nullptr;
return true;
}
int invoke(int a, int b)
{
if(m_funcProc != nullptr)
{
return m_funcProc(a, b); //函数指针调用
}
return 0;
}
private:
funcProc m_funcProc;
};
int add(int a, int b)
{
return a + b;
}
int main()
{
CFunc_ptr func;
func.attach(add);
int ret = func.invoke(3, 6);
printf("ret = %d\n", ret);
return 0;
}
这个类很简单,只能支持一种类型的函数指针的注册,如果是不同的类型则需要用到模板了。
#include <stdio.h>
#include <stdlib.h>
template <class R, class T1, class T2>
class CFunction
{
typedef R (*funcProc)(T1 a, T2 b);
public:
CFunction(): mFuncProc(nullptr)
{
}
~CFunction()
{
mFuncProc = nullptr;
}
public:
bool attach(funcProc func)
{
if(mFuncProc != func)
{
mFuncProc = func;
return true;
}
return false;
}
R invoke(T1 a, T2 b)
{
if(mFuncProc != nullptr)
{
return mFuncProc(a, b);
}
}
private:
funcProc mFuncProc;
};
int add(int a, int b)
{
return a + b;
}
int main()
{
CFunction<int, int, int> func;
func.attach(add);
int ret = func.invoke(5, 5);
printf("ret = %d\n", ret);
return 0;
}
这里声明了一个类模板,一共 3 个参数,这 3 个参数用来声明一个函数指针,一个参数作为函数的返回值,其他为函数参数。通过这 3 个参数,你可以定义不同类型的函数指针了。而要达到观察者模式那种类型,还需要支持多个函数指针的注册,其实就是要定义函数指针数组,也可以用std库容器,如下最简单的数组形式:
#include <stdio.h>
#include <stdlib.h>
template <class R, class T1, class T2>
class CFunction
{
typedef R (*funcProc)(T1 a, T2 b);
public:
CFunction(int maxSize): mCurrentPos(0), mSize(maxSize), mFuncProc(nullptr)
{
mFuncProc = new funcProc [mSize];
}
~CFunction()
{
mFuncProc = nullptr;
}
public:
bool attach(funcProc func)
{
if(mFuncProc[mCurrentPos] != func)
{
mFuncProc[mCurrentPos] = func;
mCurrentPos++;
return true;
}
return false;
}
// invoke one by one
R invoke(T1 a, T2 b)
{
for(int i = 0; i < mSize; i++)
{
if(mFuncProc[i] != nullptr)
{
mFuncProc[i](a, b);
}
}
}
private:
int mCurrentPos; //当前函数指针数组位置
int mSize; //最大支持注册个数
funcProc *mFuncProc;
};
void add1(int a, int b)
{
int ret = a + b;
printf("in add1 ret = %d\n", ret);
}
void add2(int a, int b)
{
int ret = a + b;
printf("in add2 ret = %d\n", ret);
}
void add3(int a, int b)
{
int ret = a + b;
printf("in add3 ret = %d\n", ret);
}
int main()
{
CFunction<void, int, int> func(3);
func.attach(add1);
func.attach(add2);
func.attach(add3);
func.invoke(5, 5);
return 0;
}
实际项目中会用到宏及模板来定义各种类型,包括参数个数、参数类型。这个下次再贴出来。